From Select in doctrine 2 - doctrine-orm

How do I do this in doctrine2 QB or DQL.
SELECT * FROM
(
select * from my_table order by timestamp desc
) as my_table_tmp
group by catid
order by nid desc

I think your query is the same as:
SELECT *
FROM my_table
GROUP BY catid
HAVING timestamp = MAX(timestamp)
ORDER BY nid DESC
;
If it is correct, then you should be able to do:
$qb->select('e')
->from('My\Entities\Table', 'e')
->groupBy('e.catid')
->having('e.timestamp = MAX(e.timestamp)')
->orderBy('nid', 'DESC')
;
Or, directly using DQL:
SELECT e
FROM My\Entities\Table e
GROUP BY e.catid
HAVING e.timestamp = MAX(e.timestamp)
ORDER BY e.nid DESC
;
Hope this helps and works! ;)

Related

Redshift Error when executing the delete script with EXISTS function. The Select runs fine for this query

This Redshift query fails -
DELETE FROM TBL_1 stg
WHERE EXISTS (
WITH CCDA as (
SELECT
row_number() OVER (PARTITION BY emp_id,customer_id ORDER BY seq_num desc) rn
, *
FROM TBL_2
WHERE end_dt > (SELECT max(end_dt) FROM TBL_3)
)
SELECT emp_id,customer_id FROM CCDA WHERE rn = 1
AND stg.emp_id = CCDA.emp_id
AND stg.customer_id = CCDA.customer_id
);
Error: Invalid operation: syntax error at or near "stg"
However, the below query runs fine -
SELECT * FROM TBL_1 stg
WHERE EXISTS (
WITH CCDA as (
SELECT
row_number() OVER (PARTITION BY emp_id,customer_id ORDER BY seq_num desc) rn
, *
FROM TBL_2
WHERE end_dt > (SELECT max(end_dt) FROM TBL_3)
)
SELECT emp_id,customer_id FROM CCDA WHERE rn = 1
AND stg.emp_id = CCDA.emp_id
AND stg.customer_id = CCDA.customer_id
);
Am I missing something?
You cannot use an alias in a DELETE statement for the target table. "stg" cannot be used as the alias and this is why you are getting this error.
Also to reference other tables in a DELETE statement you need to use the USING clause.
See: https://docs.aws.amazon.com/redshift/latest/dg/r_DELETE.html
A quick stab of what this would look like (untested):
WITH CCDA as (
SELECT
row_number() OVER (PARTITION BY emp_id,customer_id ORDER BY seq_num desc) rn
, *
FROM TBL_2
WHERE end_dt > (SELECT max(end_dt) FROM TBL_3)
)
DELETE FROM TBL_1
USING CCDA
WHERE CCDA.rn = 1
AND TBL_1.emp_id = CCDA.emp_id
AND TBL_1.customer_id = CCDA.customer_id
;

django annotate based on another annotate create a duplicate query

I want to calculate number of group members (no_members), sum of the points of the group members(point) and average point per person(avg_point) for each group with annotation:
groups = StudyGroup.objects.filter(group_filter).select_related('parent').annotate(
no_members=Count('student', distinct=True),
point=Sum('student__point__point', filter=point_filter),
avg_point=ExpressionWrapper(F('point') / F('no_members'), output_field=FloatField()))
but when I check query (groups.query) in avg_point instead of use point/no_members query is SUM(study_league_point.point) / COUNT(DISTINCT users_student.user_id) (point and no_members calculate again). query is:
SELECT
`study_league_studygroup`.`id`,
`study_league_studygroup`.`name`,
`study_league_studygroup`.`parent_id`,
COUNT(DISTINCT `users_student`.`user_id`) AS `no_members`,
SUM(`study_league_point`.`point`) AS `point`,
(
SUM(`study_league_point`.`point`) / COUNT(DISTINCT `users_student`.`user_id`)
) AS `avg_point`,
`layers_layer`.`id`,
`layers_layer`.`name`,
`layers_layer`.`type_id`,
`layers_layer`.`parent_id`,
`layers_layer`.`created`,
`layers_layer`.`default`,
`layers_layer`.`lft`,
`layers_layer`.`rght`,
`layers_layer`.`tree_id`,
`layers_layer`.`level`
FROM
`study_league_studygroup`
LEFT OUTER JOIN `users_student` ON (
`study_league_studygroup`.`id` = `users_student`.`study_group_id`
)
LEFT OUTER JOIN `study_league_point` ON (
`users_student`.`user_id` = `study_league_point`.`student_id`
)
INNER JOIN `layers_layer` ON (
`study_league_studygroup`.`parent_id` = `layers_layer`.`id`
)
GROUP BY
`study_league_studygroup`.`id`
but I want use (point / no_members) AS avg_point instead of (SUM(study_league_point.point) / COUNT(DISTINCT users_student.user_id)) AS avg_point

rewrite redshift query as athena

I am trying to convert this redshift query to athena.
select
a.customerid,
a.country,
a.stockcode,
a.description,
a.invoicedate,
a.sales_amt,
(b.nbr_months_active) as nbr_months_active
from
ecommerce_sales_data a
inner join (
select
customerid,
count(
distinct(
DATE_PART(y, cast(invoicedate as date)) || '-' || LPAD(
DATE_PART(mon, cast(invoicedate as date)),
2,
'00'
)
)
) as nbr_months_active
from
ecommerce_sales_data
group by
1
) b on a.customerid = b.customerid
This is what I have tried. It returns the results. But I am not sure if the results will match with redshift query in all cases.
WITH students_results(InvoiceNo,StockCode,Description,Quantity,InvoiceDate,UnitPrice,CustomerID,Country) AS (VALUES
('536365','85123A','WHITE HANGING HEART T-LIGHT HOLDER','6','12/1/2010 8:26','2.55','17850','United Kingdom'),
('536365','71053','WHITE METAL LANTERN','6','12/1/2010 8:26','3.39','17850','United Kingdom'),
('536365','84406B','CREAM CUPID HEARTS COAT HANGER','8','12/1/2010 8:26','2.75','17850','United Kingdom')
)
select
a.customerid,
a.country,
a.stockcode,
a.description,
a.invoicedate,
cast(a.quantity as decimal(11,2)) * cast(a.unitprice as decimal(11,2)) as sales_amt,
(b.nbr_months_active) as nbr_months_active
from
students_results a
inner join (
select
customerid,
count(
distinct(
date_format(date_parse(invoicedate,'%m/%d/%Y %k:%i'), '%Y-%m')
)) as nbr_months_active
FROM students_results group by customerid) as b
on a.customerid = b.customerid
The source of Redshift query is here:
https://aws.amazon.com/blogs/machine-learning/build-multi-class-classification-models-with-amazon-redshift-ml/

How do i get table name and column name using sequence name in postgres?

I know the sequence name but I don't know the table name and column name of it.
So please help me how to find it.
Slight improvisation using #a_horse_with_no_name's answer. The below query will also give the schema name and sequence name. So, this gives you the data with schema,table,column and sequence names as single result
select ts.nspname as object_schema,
tbl.relname as table_name,
col.attname as column_name,
s.relname as sequence_name
from pg_class s
join pg_namespace sn on sn.oid = s.relnamespace
join pg_depend d on d.refobjid = s.oid and d.refclassid='pg_class'::regclass
join pg_attrdef ad on ad.oid = d.objid and d.classid = 'pg_attrdef'::regclass
join pg_attribute col on col.attrelid = ad.adrelid and col.attnum = ad.adnum
join pg_class tbl on tbl.oid = ad.adrelid
join pg_namespace ts on ts.oid = tbl.relnamespace
where s.relkind = 'S'
-- and s.relname = 'your_sequence_name_here'
and d.deptype in ('a', 'n');
Assuming it's a sequence that is owned by a column e.g. because the column is defined as serial or identity then you can get that information by looking at pg_depend and join that to pg_class (and others)
select tbl.relname as table_name,
col.attname as column_name
from pg_class s
join pg_namespace sn on sn.oid = s.relnamespace
join pg_depend d on d.refobjid = s.oid and d.refclassid='pg_class'::regclass
join pg_attrdef ad on ad.oid = d.objid and d.classid = 'pg_attrdef'::regclass
join pg_attribute col on col.attrelid = ad.adrelid and col.attnum = ad.adnum
join pg_class tbl on tbl.oid = ad.adrelid
join pg_namespace ts on ts.oid = tbl.relnamespace
where s.relkind = 'S'
and s.relname = 'your_sequence_name_her'
and d.deptype in ('a', 'n');
Another option is to look at the default value of the columns and check if it contains the sequence name:
select tbl.relname as table_name,
col.attname as column_name
from pg_attrdef ad
join pg_attribute col on col.attrelid = ad.adrelid and col.attnum = ad.adnum
join pg_class tbl on tbl.oid = ad.adrelid
where pg_get_expr(ad.adbin, ad.adrelid) like '%your_sequence_name_here%'
This would also work for sequences that are not owned by a column.

Need help on Regular expression to extract sql sub query

i am new to regx...i want to get the subquery from given query using regular expression.
For example i have query like following
Select * from (
select * from Table_A where ID = 90
UNION
select * from Table_B where ID = 90
) as SUBQUERY left join TABL_ABC abc ON (abc.id = SUBQUERY.id)
now i want my regular expression to match following lines only:
select * from Table_A where ID = 90
UNION
select * from Table_B where ID = 90
Please help me, Thank you in advance...
If it is a simple subquery without additional braces, you can just use this regexp
/\(\s*(select[^)]+)\)/i
<?php
$sql = 'Select * from ( select * from Table_A where ID = 90 UNION select * from Table_B where ID = 90 ) as SUBQUERY left join TABL_ABC abc ON (abc.id = SUBQUERY.id)';
if( preg_match('/\(\s*(select.+)\) as /iU', $sql, $matched ) ){
$subquery = trim( $matched[1] );
var_dump( $subquery );
}