how to replace duplicated subquery? - postgresql

I got a query
SELECT name AS name,
count(group_name) AS all_test_cases,
(SELECT count(*) FROM test_cases AS tc2 WHERE tc2.group_name = tg.name AND status = 'OK' ) AS passed_test_cases,
tg.test_value * (SELECT count(*) FROM test_cases AS tc2 WHERE tc2.group_name = name AND status = 'OK') AS total_value
FROM test_groups AS tg
LEFT JOIN test_cases AS tc
ON tg.name = tc.group_name
GROUP BY name, test_value
ORDER BY total_value DESC, name ASC
How I can replace duplicated subquery:
tg.test_value * (SELECT count(*) FROM test_cases AS tc2 WHERE tc2.group_name = name AND status = 'OK') AS total_value
with something more efficient in postgres without stored procedure?

Does this work for you?
with cte_test_cases as (
SELECT group_name,
count(*) filter (where status = 'OK') as passed_test_cases,
count(*) as all_test_cases
FROM test_cases
GROUP BY group_name
)
SELECT tg.name,
tc.all_test_cases,
tc.passed_test_cases,
tg.test_value * tc.passed_test_cases AS total_value
FROM test_groups AS tg
LEFT JOIN cte_test_cases AS tc
ON tg.name = tc.group_name
ORDER BY total_value DESC, name ASC

Related

If the object we made by the group is null, I want to give [ ] instead postgresql

with
zakaz as (
select
o.*,
(select f_name from clients where id = o.client_id) as f_name,
(select l_name from clients where id = o.client_id) as l_name,
(select phone from clients where id = o.client_id) as phone,
(select name from item_types where id = o.item_type_id) as item_name,
(select name from trailer_types where id = o.trailer_type_id) as trailer_name,
(select name from cover_types where id = o.cover_type_id) as cover_name,
(select name from cities where id = o.from_city_id) as from_city,
(select name from cities where id = o.to_city_id) as to_city,
(select name from transport_types where id = o.transport_type_id) as transport_type,
(select first_name || ' ' || last_name || ' ' || middle_name as name from workers where id = o.logist_id) as logist_name
from orders as o
where o.transport_type_id = (select id from transport_types where name = $tt$${transport_type}$tt$)
${ where_key ? `and ${where_key} = $v$${where_val}$v$` : ``}
order by o.created_at
),
zakaz_j_agg as (
select
COALESCE(json_agg(zakaz.*), '[]') as array
from zakaz
group by zakaz.status
)
select
json_agg(ord.*) as result
from zakaz_j_agg as ord
Replace json_agg(ord.*) as result with coalesce(json_agg(ord.*), '[]') as result. The same pattern is used in the zakaz_j_agg CTE.
with
zakaz as (... your CTE query ...),
zakaz_j_agg as (... your CTE query ...)
select
coalesce(json_agg(ord.*), '[]') as result
from zakaz_j_agg as ord;

Does Redshift support User-Defined Variables in SELECT?

I'm reviewing some of our Redshift queries and found cases with multiple levels of nested select like the one below:
LEFT JOIN
(
SELECT *
FROM (
SELECT
id,
created_at,
min(created_at) OVER (PARTITION BY id, slug) AS transition_date
FROM table
WHERE status = 'cancelled'
GROUP BY id, Y, Z, created_at
)
WHERE created_at = transition_date
) t1 ON b.id = t1.id
if this were MySQL, I would've done something like this to remove one level of nested select:
LEFT JOIN
(
SELECT
id,
created_at,
#tdate := min(created_at) OVER (PARTITION BY id, slug) AS transition_date
FROM table
WHERE status = 'cancelled' and #tdate = bul.created_at
GROUP BY id, Y, Z, created_at
) t1 ON b.id = t1.id
Is it possible to so something similar in RedShift?
--- update
forgot to include GROUP BY in the nested SELECT, which may affect the answer
You can move the condition for the transition_date into the JOIN condition:
LEFT JOIN
(
SELECT
id,
created_at,
min(created_at) OVER (PARTITION BY id, slug) AS transition_date
FROM table
WHERE status = 'cancelled'
) t1 ON b.id = t1.id AND t1.created_at = t1.transition_date

Postgresql nested select max(sum())

My Query:
select table.attribute, count(table.attribute) AS cnt from table
group by table.attribute
order by cnt desc;
The output is something like:
attribute | cnt
-----------+-----
A | 2
B | 2
G | 1
F | 1
But i only want the max values (A & B).
You can do this with a single level of nesting:
select attribute,
cnt
from (
select attribute,
count(*) AS cnt,
max(count(*)) over () as max_cnt
from t
group by attribute
) t
where cnt = max_cnt;
You can use the power of CTE to achieve this:
WITH count_values
AS (SELECT table.attribute,
Count(table.attribute) AS cnt
FROM table
GROUP BY table.attribute),
max_values
AS (SELECT Max(cnt) AS max_cnt
FROM (SELECT cnt
FROM count_values) sub)
SELECT *
FROM count_values cv
JOIN max_values mv
ON mv.max_cnt = cv.cnt;
you can use rank as below
with cte as (
select *, Rank() over(order by cnt desc) as rnk from yourattribute
) select * from cte where rnk = 1

How to pull out the employees who have 'first name,lastname and date of birth' as same from Employee table

I need to pull out the records whose First name,lastname and date of birth are of same.
Please find the below example.
Employeeid firstname lastname DOB
00010 ravi sagi 22/01/1990
00035 ravi sagi 22/01/1990
00060 vasanth guptha 20/01/1987
00115 vasanth guptha 20/01/1987
Can you please help in writing the query.
Try this:
select *
from
(
select *,
count(*) over(partition by firstname, lastname, DOB) as CC
from YourTable
) as T
where T.CC > 1
You can JOIN the table to itself comparing the firstname, lastname and DOB to make sure they are the same value and then that the employeeid is not the same:
select *
from yourtable t1
inner join yourtable t2
on t1.firstname = t2.firstname
and t1.lastname = t2.lastname
and t1.dob = t2.dob
and t1.empid != t2.empid
the above query could display duplicate records, so you could use the following (see SQL Fiddle with Demo):
select DISTINCT t1.empid,
t1.firstname,
t1.lastname,
t1.DOB
from yourtable t1
inner join yourtable t2
on t1.firstname = t2.firstname
and t1.lastname = t2.lastname
and t1.dob = t2.dob
and t1.empid != t2.empid
Or you can use EXISTS (See SQL Fiddle with Demo):
select t1.empid,
t1.firstname,
t1.lastname,
t1.DOB
from yourtable t1
where exists (SELECT *
FROM yourtable t2
WHERE t1.firstname = t2.firstname
and t1.lastname = t2.lastname
and t1.dob = t2.dob
and t1.empid != t2.empid)

ordering by rows

OK so I have a query I am trying to build.. I have 2 tables, table1 has a bunch of regular records as normal with a unique ID (auto increment) and table2 has records that include some of those ids from table1. I am trying to order by the highest records with that same ID in table1.. Heres what I've got:
SELECT * FROM table1
WHERE table1.status = 1
AND (SELECT COUNT(*) FROM table2 WHERE table2.tbl1_id = table1.id)
ORDER BY table1.id DESC
Thanks :)
SELECT table1.id
FROM table1
LEFT JOIN table2 ON table2.tbl1_id = table1.id
WHERE table1.status = 1
GROUP BY table1.id
ORDER BY COUNT(table2.tbl1_id) DESC
Try this:
SELECT a.*, b.cnt
FROM table1 a LEFT JOIN
(
SELECT tbl1_id, COUNT(*) cnt
FROM table2
GROUP BY tbl1_id
) b
ON a.id = b.tbl1_id
WHERE table1.status = 1
ORDER BY cnt DESC