SUM data only when COUNT(*) > 0 - sql

Here is what I have so far...
SELECT pr.[name], SUM(COALESCE(qm.iscompleted,0)) count_yes,
SUM(COALESCE(qm.iscompleted,1)) count_no,
COUNT(p.id) AS tot
FROM (aco.practices pr
left JOIN aco.patients_practices ppr ON (ppr.practiceid = pr.id)
left JOIN aco.patients p ON (p.id = ppr.patientid)
LEFT JOIN aco.qmheader qm ON (qm.patientid = p.id AND qm.practiceid = pr.id)
)
WHERE (pr.parentaco = 30982)
GROUP BY pr.[name]
ORDER BY pr.[name]
Here are some results
name count_yes count_no tot
name1 0 1 0
name2 0 1 0
name3 0 273 273
name4 0 114 114
For the most part it is correct, the only thing I need is to not SUM on the count_no if the tot is 0.
Is there a way to do this easily?
Thanks.

Change your select clause to:
SELECT pr.[name],
SUM(COALESCE(qm.iscompleted,0)) AS count_yes,
(case when COUNT(p.id) > 0 then
SUM(COALESCE(qm.iscompleted,1))
else
0 end) AS count_no,
COUNT(p.id) AS tot

Use the HAVING clause:
SELECT pr.[name], SUM(COALESCE(qm.iscompleted,0)) count_yes,
SUM(COALESCE(qm.iscompleted,1)) count_no,
COUNT(p.id) AS tot
FROM (aco.practices pr
left JOIN aco.patients_practices ppr ON (ppr.practiceid = pr.id)
left JOIN aco.patients p ON (p.id = ppr.patientid)
LEFT JOIN aco.qmheader qm ON (qm.patientid = p.id AND qm.practiceid = pr.id)
)
WHERE (pr.parentaco = 30982)
GROUP BY pr.[name]
HAVING COUNT(p.id) = 0
ORDER BY pr.[name]

Related

Check col1 if duplicate then check col2 if distinct

Hey guys I've been struggling to get a simple query done in SnowFlake.
A sample of the data is explained below,
Number
ID
2559
23
2559
33
2559
55
2550
89
2499
14
2499
14
Based on the table above I would like to create a column that checks if (column Number) have duplicated values if yes; then check (column ID) if the values associated with that Number were duplicated or distinct. If values were duplicated then return 0 if values were distinct then return 1.
The desired outcome is as follows,
Number
ID
Check
2559
23
1
2559
33
1
2559
55
1
2550
89
0
2499
14
0
2499
14
0
and the last outcome should be on the Number column level (group by) and would be like the following table,
Number
Check
2559
1
2550
0
2499
0
Any suggestions are appreciated.
Edited tables
The scenario has changed based on new requirements
The original table have two IDs (ID1 and ID2) and those IDs must be linked to two different tables T-ID1 and T-ID2.
Number
ID1
ID2
2559
23
null
2559
33
null
2559
55
null
2550
89
null
2499
14
null
2499
14
null
2498
null
14
2498
null
50
2498
null
null
So the idea is if Number has duplicated IDs (in ID1 or ID2) then return 1, if Number has unique ID (in ID1 or ID2) then return ID1 or ID2. if Number have null values for ID1 and ID2 then ignore the entire row.
This is the query I am using - everything works based on solution provided below, but I am getting nulls along with ID values.
ID1 is linked to Supplier_ID_Ekuep and ID2 is linked to Supplier_ID_Qava.
select wbd.WAYBILL_ID, sup.WAYBILL_NO,
sup.Supplier_ID_Qava, supq.Supplier_Qava, supq.Supllier_City_Qava, supq.Supplier_Qava_Add,
sup.Supplier_ID_Ekuep, supc.Supplier_Ekuep, supc.Supllier_City_Ekuep, supc.Supplier_Ekuep_Add
from WAYBILL_PRODUCTS wbd
left join (select wb.WAYBILL_ID, ow.WAYBILL_NO,
case when mult.multi_supp_qava = 1 then '1'
when mult.multi_supp_qava = 0 then op.ID_Supplier_Qava
else null end as Supplier_ID_Qava,
case when mult.multi_supp_ekuep = 1 then '1'
when mult.multi_supp_ekuep = 0 then op.ID_Supplier_Ekuep
else null end as Supplier_ID_Ekuep
from WAYBILL_PRODUCTS wb
left join (select ID, ORDER_ID, WAYBILL_NO from ORDER_WAYBILLS) ow on wb.WAYBILL_ID = ow.id
left join (select opr.ID_ORDER, opr.ID_PRODUCT, ss.ID_Supplier_Ekuep, ss.ID_Supplier_Qava
from ORDER_PRODUCTS opr
left join (select s.id, supc.*, supq.*
from SUPPLIERS s
left join (select ID_SUPPLIER as ID_Supplier_Ekuep
from EKUEP_KSA_EKUEP_STAGING.PS_SUPPLIER where USED_SUPPLIER_ID is null) supc on supc.ID_Supplier_Ekuep = s.ID_SUPPLIER and s.STORE_ID = 1
left join (select ID_SUPPLIER as ID_Supplier_Qava
from QAVASHOP_KSA_QAVAISH_MAINSHOP.PS_SUPPLIER where USED_SUPPLIER_ID is null) supq on supq.ID_Supplier_Qava = s.ID_SUPPLIER and s.STORE_ID = 2) ss on opr.SUPPLIER_ID = ss.ID
group by opr.ID_ORDER, opr.ID_PRODUCT, ss.ID_Supplier_Ekuep, ss.ID_Supplier_Qava) op on op.ID_PRODUCT = wb.PRODUCT_ID and op.ID_ORDER = ow.ORDER_ID
------------------------------------------------------------------------------------------------------------------------
left join (select wb.WAYBILL_ID, ow.WAYBILL_NO,
(count(distinct op.ID_Supplier_Qava) > 1)::int as multi_supp_qava,
(count(distinct op.ID_Supplier_Ekuep) > 1)::int as multi_supp_ekuep
from WAYBILL_PRODUCTS wb
left join (select ID, ORDER_ID, WAYBILL_NO from ORDER_WAYBILLS) ow on wb.WAYBILL_ID = ow.id
left join (select opr.ID_ORDER, opr.ID_PRODUCT, ss.ID_Supplier_Ekuep, ss.ID_Supplier_Qava
from ORDER_PRODUCTS opr
left join (select s.id, supc.ID_Supplier_Ekuep, supq.ID_Supplier_Qava
from SUPPLIERS s
left join (select ID_SUPPLIER as ID_Supplier_Ekuep
from EKUEP_KSA_EKUEP_STAGING.PS_SUPPLIER where USED_SUPPLIER_ID is null) supc on supc.ID_Supplier_Ekuep = s.ID_SUPPLIER and s.STORE_ID = 1
left join (select ID_SUPPLIER as ID_Supplier_Qava
from QAVASHOP_KSA_QAVAISH_MAINSHOP.PS_SUPPLIER where USED_SUPPLIER_ID is null) supq on supq.ID_Supplier_Qava = s.ID_SUPPLIER and s.STORE_ID = 2
) ss on opr.SUPPLIER_ID = ss.ID
group by opr.ID_ORDER, opr.ID_PRODUCT, ss.ID_Supplier_Ekuep, ss.ID_Supplier_Qava) op on op.ID_PRODUCT = wb.PRODUCT_ID and op.ID_ORDER = ow.ORDER_ID
where _FIVETRAN_DELETED = 0
group by wb.WAYBILL_ID, ow.WAYBILL_NO) mult on mult.WAYBILL_NO = ow.WAYBILL_NO
------------------------------------------------------------------------------------------------------------------------
group by wb.WAYBILL_ID, ow.WAYBILL_NO, mult.multi_supp_qava, mult.multi_supp_ekuep, op.ID_Supplier_Qava, op.ID_Supplier_Ekuep) sup on wbd.WAYBILL_ID = sup.WAYBILL_ID
left join
(select ps.ID_SUPPLIER as ID_Supplier_Qava,
ps.name as Supplier_Qava,
listagg(distinct pa.CITY, ', ') as Supllier_City_Qava,
ps.DATE_ADD as Supplier_Qava_Add
from QAVASHOP_KSA_QAVAISH_MAINSHOP.PS_SUPPLIER ps
left join (select * from QAVASHOP_KSA_QAVAISH_MAINSHOP.PS_ADDRESS) pa on pa.ID_SUPPLIER = ps.ID_SUPPLIER and pa._FIVETRAN_DELETED = 0
where ps.USED_SUPPLIER_ID is null and ps._FIVETRAN_DELETED = 0
group by ID_Supplier_Qava, Supplier_Qava, Supplier_Qava_Add) supq on supq.ID_Supplier_Qava = sup.Supplier_ID_Qava
left join
(select ps.ID_SUPPLIER as ID_Supplier_Ekuep,
ps.name as Supplier_Ekuep,
listagg(distinct pa.CITY, ', ') as Supllier_City_Ekuep,
ps.DATE_ADD as Supplier_Ekuep_Add
from EKUEP_KSA_EKUEP_STAGING.PS_SUPPLIER ps
left join (select * from EKUEP_KSA_EKUEP_STAGING.PS_ADDRESS) pa on pa.ID_SUPPLIER = ps.ID_SUPPLIER and pa._FIVETRAN_DELETED = 0
where ps.USED_SUPPLIER_ID is null and ps._FIVETRAN_DELETED = 0
group by ID_Supplier_Ekuep, Supplier_Ekuep, Supplier_Ekuep_Add) supc on supc.ID_Supplier_Ekuep = sup.Supplier_ID_Ekuep
where _FIVETRAN_DELETED = 0
group by wbd.WAYBILL_ID, sup.WAYBILL_NO,
sup.Supplier_ID_Qava, supq.Supplier_Qava, supq.Supllier_City_Qava, supq.Supplier_Qava_Add,
sup.Supplier_ID_Ekuep, supc.Supplier_Ekuep, supc.Supllier_City_Ekuep, supc.Supplier_Ekuep_Add
The output I am getting for Waybill_No = 43265104 is as follows, I just want to get rid of the null row.
WITH data(num, id) AS (
SELECT * FROM VALUES
(2559, 23),
(2559, 33),
(2559, 55),
(2550, 89),
(2499, 14),
(2499, 14)
)
SELECT
num,
id,
count(*) over(partition by num) as num_dup,
count(distinct id)over(partition by num) as id_dup,
iff(num_dup > 1 AND num_dup = id_dup, 1, 0) as "check"
FROM data;
gives:
NUM
ID
NUM_DUP
ID_DUP
check
2559
23
3
3
1
2559
33
3
3
1
2559
55
3
3
1
2550
89
1
1
0
2499
14
2
1
0
2499
14
2
1
0
Extra Data:
WITH data(num, id) AS (
SELECT * FROM VALUES
(2559, 23),
(2559, 33),
(2559, 33),
(2559, 55),
(2550, 89),
(2499, 14),
(2499, 14)
)
SELECT
num,
id,
count(*) over(partition by num) as num_dup,
count(distinct id)over(partition by num) as id_dup,
iff(num_dup > 1 AND num_dup = id_dup, 1, 0) as "check"
FROM data;
if we make 2559 have two 33's then it show change to 0/false
NUM
ID
NUM_DUP
ID_DUP
check
2559
23
4
3
0
2559
33
4
3
0
2559
33
4
3
0
2559
55
4
3
0
2550
89
1
1
0
2499
14
2
1
0
2499
14
2
1
0
Last Step:
WITH data(num, id) AS (
SELECT * FROM VALUES
(2559, 23),
(2559, 33),
(2559, 55),
(2550, 89),
(2499, 14),
(2499, 14)
)
SELECT
num,
iff(count(*) > 1 AND count(*) = count(distinct id), 1, 0) as output
FROM data
GROUP BY 1;
gives:
NUM
OUTPUT
2559
1
2550
0
2499
0
left join (
select
ID,
ORDER_ID,
WAYBILL_NO
from ORDER_WAYBILLS
) ow
on wb.WAYBILL_ID = ow.id
should just be:
LEFT JOIN order_waybills AS ow
ON wb.waybill_id = ow.id
Gaint Refactoing Starts Here
So I start refactoring this SQL, the first part was to ignore my prior "this could be simpler" and move that into a CTE ob_cte, so it was "just simple" then I notice the first two sections had large block you noted as op that where the same, so that becomes a CTE op_cte also then that gives us:
WITH ob_cte AS (
SELECT
id,
order_id,
waybill_no
FROM order_waybills
), op_etc AS (
SELECT
opr.id_order,
opr.id_product,
ss.id_supplier_ekuep,
ss.id_supplier_qava
FROM order_products AS opr
LEFT JOIN (
SELECT
s.id,
supc.id_supplier_ekuep,
supq.id_supplier_qava
FROM suppliers AS s
LEFT JOIN (
SELECT
id_supplier AS id_supplier_ekuep
FROM ekuep_ksa_ekuep_staging.ps_supplier
WHERE used_supplier_id IS NULL
) AS supc
ON supc.id_supplier_ekuep = s.id_supplier
AND s.store_id = 1
LEFT JOIN (
SELECT
id_supplier AS id_supplier_qava
FROM qavashop_ksa_qavaish_mainshop.ps_supplier
WHERE used_supplier_id IS NULL
) AS supq
ON supq.id_supplier_qava = s.id_supplier
AND s.store_id = 2
) AS ss
ON opr.SUPPLIER_ID = ss.ID
GROUP BY opr.id_order, opr.id_product, ss.id_supplier_ekuep, ss.id_supplier_qava
)
SELECT
wbd.waybill_id,
sup.waybill_no,
sup.supplier_id_qava,
supq.supplier_qava,
supq.supllier_city_qava,
supq.supplier_qava_add,
sup.supplier_id_ekuep,
supc.supplier_ekuep,
supc.supllier_city_ekuep,
supc.supplier_ekuep_add
FROM waybill_products AS wbd
LEFT JOIN (
SELECT
wb.waybill_id,
ow.waybill_no,
CASE
WHEN mult.multi_supp_qava = 1 THEN '1'
WHEN mult.multi_supp_qava = 0 THEN op.ID_Supplier_Qava
ELSE NULL
end as supplier_id_qava,
case
WHEN mult.multi_supp_ekuep = 1 THEN '1'
WHEN mult.multi_supp_ekuep = 0 THEN op.ID_Supplier_Ekuep
ELSE NULL
END AS supplier_id_ekuep
FROM waybill_products AS wb
LEFT JOIN ob_cte AS ow
ON wb.waybill_id = ow.id
LEFT JOIN op_etc AS op
ON op.id_product = wb.product_id
AND op.id_order = ow.order_id
------------------------------------------------------------------------------------------------------------------------
left join (
select
wb.WAYBILL_ID,
ow.WAYBILL_NO,
(count(distinct op.ID_Supplier_Qava) > 1)::int as multi_supp_qava,
(count(distinct op.ID_Supplier_Ekuep) > 1)::int as multi_supp_ekuep
from WAYBILL_PRODUCTS wb
LEFT JOIN ob_cte AS ow
ON wb.waybill_id = ow.id
left join op_etc AS op
on op.ID_PRODUCT = wb.PRODUCT_ID
and op.ID_ORDER = ow.ORDER_ID
where _FIVETRAN_DELETED = 0
group by wb.WAYBILL_ID, ow.WAYBILL_NO
) AS mult
on mult.WAYBILL_NO = ow.WAYBILL_NO
------------------------------------------------------------------------------------------------------------------------
group by wb.WAYBILL_ID, ow.WAYBILL_NO, mult.multi_supp_qava, mult.multi_supp_ekuep, op.ID_Supplier_Qava, op.ID_Supplier_Ekuep
) AS sup
on wbd.WAYBILL_ID = sup.WAYBILL_ID
left join (
select
ps.id_supplier AS id_supplier_qava,
ps.name AS supplier_qava,
ps.date_add AS supplier_qava_add,
LISTAGG(DISTINCT pa.CITY, ', ') AS supllier_city_qava
from QAVASHOP_KSA_QAVAISH_MAINSHOP.PS_SUPPLIER ps
left join (
select *
from QAVASHOP_KSA_QAVAISH_MAINSHOP.PS_ADDRESS
) pa
ON pa.ID_SUPPLIER = ps.ID_SUPPLIER
AND pa._fivetran_deleted = 0
WHERE ps.USED_SUPPLIER_ID is null
AND ps._fivetran_deleted = 0
GROUP BY 1, 2, 3
) AS supq
on supq.ID_Supplier_Qava = sup.Supplier_ID_Qava
left join (
select
ps.id_supplier AS id_supplier_ekuep,
ps.name AS supplier_ekuep,
ps.date_add AS supplier_ekuep_add,
LISTAGG(DISTINCT pa.CITY, ', ') AS supllier_city_ekuep
FROM ekuep_ksa_ekuep_staging.ps_supplier AS ps
LEFT JOIN FROM ekuep_ksa_ekuep_staging.ps_address AS pa
ON pa.id_supplier = ps.id_supplier
and pa._fivetran_deleted = 0
WHERE ps.used_supplier_id IS NULL
and ps._fivetran_deleted = 0
GROUP BY 1, 2, 4
) AS supc
ON supc.id_supplier_ekuep = sup.supplier_id_ekuep
WHERE _fivetran_deleted = 0
GROUP BY wbd.waybill_id, sup.waybill_no,
sup.supplier_id_qava, supq.supplier_qava,
supq.supllier_city_qava, supq.supplier_qava_add,
sup.supplier_id_ekuep, supc.supplier_ekuep,
supc.supllier_city_ekuep, supc.supplier_ekuep_add;
Now op_etc itself, that GROUP BY at the end is really just a DISTINCT so we can swap that in. Also in ss of that op_cte
SELECT
s.id,
supc.id_supplier_ekuep,
supq.id_supplier_qava
FROM suppliers AS s
LEFT JOIN (
SELECT
id_supplier AS id_supplier_ekuep
FROM ekuep_ksa_ekuep_staging.ps_supplier
WHERE used_supplier_id IS NULL
) AS supc
ON supc.id_supplier_ekuep = s.id_supplier
AND s.store_id = 1
LEFT JOIN (
SELECT
id_supplier AS id_supplier_qava
FROM qavashop_ksa_qavaish_mainshop.ps_supplier
WHERE used_supplier_id IS NULL
) AS supq
ON supq.id_supplier_qava = s.id_supplier
AND s.store_id = 2
those to left joins, keep only values that are NULL and then LEFT JOIN of two requirements which means we are get a row per suppliers the IS NULL can be moved to the ON with no impact, which means the rename can be moved higher up, and the sub-select dropped, so that section can become:
SELECT
s.id,
supc.id_supplier AS id_supplier_ekuep,
supq.id_supplier AS id_supplier_qava
FROM suppliers AS s
LEFT JOIN ekuep_ksa_ekuep_staging.ps_supplier AS supc
ON supc.id_supplier = s.id_supplier
AND s.store_id = 1
AND supc.used_supplier_id IS NULL
LEFT JOIN qavashop_ksa_qavaish_mainshop.ps_supplier AS supq
ON supq.id_supplier = s.id_supplier
AND s.store_id = 2
AND supq.used_supplier_id IS NULL
thus the op_cte becomes:
), op_etc AS (
SELECT DISTINCT
opr.id_order,
opr.id_product,
ss.id_supplier_ekuep,
ss.id_supplier_qava
FROM order_products AS opr
LEFT JOIN (
SELECT
s.id,
supc.id_supplier AS id_supplier_ekuep,
supq.id_supplier AS id_supplier_qava
FROM suppliers AS s
LEFT JOIN ekuep_ksa_ekuep_staging.ps_supplier AS supc
ON supc.id_supplier = s.id_supplier
AND s.store_id = 1
AND supc.used_supplier_id IS NULL
LEFT JOIN qavashop_ksa_qavaish_mainshop.ps_supplier AS supq
ON supq.id_supplier = s.id_supplier
AND s.store_id = 2
AND supq.used_supplier_id IS NULL
) AS ss
ON opr.SUPPLIER_ID = ss.ID
)
which actually means the ss can just be left joined as first order things like:
), op_etc AS (
SELECT DISTINCT
opr.id_order,
opr.id_product,
supc.id_supplier AS id_supplier_ekuep,
supq.id_supplier AS id_supplier_qava
FROM order_products AS opr
LEFT JOIN suppliers AS s
opr.SUPPLIER_ID = s.ID
LEFT JOIN ekuep_ksa_ekuep_staging.ps_supplier AS supc
ON supc.id_supplier = s.id_supplier
AND s.store_id = 1
AND supc.used_supplier_id IS NULL
LEFT JOIN qavashop_ksa_qavaish_mainshop.ps_supplier AS supq
ON supq.id_supplier = s.id_supplier
AND s.store_id = 2
AND supq.used_supplier_id IS NULL
)
ah thats much more refreshing..
in the sub-select sup` I am worried, that you are grouping by values that are not in you output set, so you will get duplicate rows
in this case block
CASE
WHEN mult.multi_supp_qava = 1 THEN '1'
WHEN mult.multi_supp_qava = 0 THEN op.ID_Supplier_Qava
ELSE NULL
end as supplier_id_qava,
you are group not by the output supplier_id_qava or it's position 3 but mult.multi_supp_qava, op.ID_Supplier_Qava
so if op.ID_Supplier_Qava is not null when mult.multi_supp_qava = 1 and can have different values, the supplier_id_qava will output 1 on both rows, but they will not merge, as op.ID_Supplier_Qava is different. This is the root of my strong dislike for using the input to the SELECT section as the grouping clauses of the aggregation of those values. because through transformation, they can become the same on the output, but remain different on the input, and produce hard to debug deuplicates. And if the flip case that they are alway safe/null/constant in the odd case, this is not clear to the SQL reader. (on this point I have to say a strong thank you for have used the aliases on select etc, as that alway confidance of where those values are coming from).
So again the GROUP BY on sup has no agration of values so this is a hidden DISTINCT, but it not giving distinct values perhaps in all cases.
So after moving some sub-selects into CTE's as I find it makes each select layer show, just what it is doing, with have to leap over smaller details we get SQL like this:
WITH ob_cte AS (
SELECT
id,
order_id,
waybill_no
FROM order_waybills
), op_etc AS (
SELECT DISTINCT
opr.id_order,
opr.id_product,
supc.id_supplier AS id_supplier_ekuep,
supq.id_supplier AS id_supplier_qava
FROM order_products AS opr
LEFT JOIN suppliers AS s
opr.SUPPLIER_ID = s.ID
LEFT JOIN ekuep_ksa_ekuep_staging.ps_supplier AS supc
ON supc.id_supplier = s.id_supplier
AND s.store_id = 1
AND supc.used_supplier_id IS NULL
LEFT JOIN qavashop_ksa_qavaish_mainshop.ps_supplier AS supq
ON supq.id_supplier = s.id_supplier
AND s.store_id = 2
AND supq.used_supplier_id IS NULL
), mult_cte AS (
SELECT
wb.waybill_id,
ow.waybill_no,
(COUNT(DISTINCT op.id_supplier_qava) > 1)::int AS multi_supp_qava,
(COUNT(DISTINCT op.id_supplier_ekuep) > 1)::int AS multi_supp_ekuep
FROM waybill_products AS wb
LEFT JOIN ob_cte AS ow
ON wb.waybill_id = ow.id
LEFT JOIN op_etc AS op
ON op.id_product = wb.product_id
AND op.id_order = ow.order_id
WHERE _fivetran_deleted = 0
GROUP BY wb.waybill_id, ow.waybill_no
), supq_cte AS (
SELECT
ps.id_supplier AS id_supplier_qava,
ps.name AS supplier_qava,
ps.date_add AS supplier_qava_add,
LISTAGG(DISTINCT pa.city, ', ') AS supllier_city_qava
FROM qavashop_ksa_qavaish_mainshop.ps_supplier AS ps
LEFT JOIN qavashop_ksa_qavaish_mainshop.ps_address AS pa
ON pa.id_supplier = ps.id_supplier
AND pa._fivetran_deleted = 0
WHERE ps.used_supplier_id is null
AND ps._fivetran_deleted = 0
GROUP BY 1, 2, 3
), supc_cte AS (
SELECT
ps.id_supplier AS id_supplier_ekuep,
ps.name AS supplier_ekuep,
ps.date_add AS supplier_ekuep_add,
LISTAGG(DISTINCT pa.city, ', ') AS supllier_city_ekuep
FROM ekuep_ksa_ekuep_staging.ps_supplier AS ps
LEFT JOIN FROM ekuep_ksa_ekuep_staging.ps_address AS pa
ON pa.id_supplier = ps.id_supplier
AND pa._fivetran_deleted = 0
WHERE ps.used_supplier_id IS NULL
AND ps._fivetran_deleted = 0
GROUP BY 1, 2, 4
), sup_cte AS (
SELECT DISTINCT
wb.waybill_id,
ow.waybill_no,
CASE
WHEN mult.multi_supp_qava = 1 THEN '1'
WHEN mult.multi_supp_qava = 0 THEN op.ID_Supplier_Qava
ELSE NULL
end as supplier_id_qava,
case
WHEN mult.multi_supp_ekuep = 1 THEN '1'
WHEN mult.multi_supp_ekuep = 0 THEN op.ID_Supplier_Ekuep
ELSE NULL
END AS supplier_id_ekuep
FROM waybill_products AS wb
LEFT JOIN ob_cte AS ow
ON wb.waybill_id = ow.id
LEFT JOIN op_etc AS op
ON op.id_product = wb.product_id
AND op.id_order = ow.order_id
------------------------------------------------------------------------------------------------------------------------
LEFT JOIN mult_cte AS mult
on mult.WAYBILL_NO = ow.WAYBILL_NO
------------------------------------------------------------------------------------------------------------------------
)
SELECT
wbd.waybill_id,
sup.waybill_no,
sup.supplier_id_qava,
supq.supplier_qava,
supq.supllier_city_qava,
supq.supplier_qava_add,
sup.supplier_id_ekuep,
supc.supplier_ekuep,
supc.supllier_city_ekuep,
supc.supplier_ekuep_add
FROM waybill_products AS wbd
LEFT JOIN sup_cte AS sup
ON wbd.WAYBILL_ID = sup.WAYBILL_ID
LEFT JOIN supq_cte AS supq
ON supq.id_supplier_qava = sup.supplier_id_qava
LEFT JOIN supc_cte AS supc
ON supc.id_supplier_ekuep = sup.supplier_id_ekuep
WHERE _fivetran_deleted = 0
GROUP BY wbd.waybill_id, sup.waybill_no,
sup.supplier_id_qava, supq.supplier_qava,
supq.supllier_city_qava, supq.supplier_qava_add,
sup.supplier_id_ekuep, supc.supplier_ekuep,
supc.supllier_city_ekuep, supc.supplier_ekuep_add;
And at the end we see again you are suffering from duplicate data, that you are trying to clean away with yet another GROUP BY.. so we will switch to a DISTINCT
SELECT DISTINCT
wbd.waybill_id,
sup.waybill_no,
sup.supplier_id_qava,
supq.supplier_qava,
supq.supllier_city_qava,
supq.supplier_qava_add,
sup.supplier_id_ekuep,
supc.supplier_ekuep,
supc.supllier_city_ekuep,
supc.supplier_ekuep_add
FROM waybill_products AS wbd
LEFT JOIN sup_cte AS sup
ON wbd.WAYBILL_ID = sup.WAYBILL_ID
LEFT JOIN supq_cte AS supq
ON supq.id_supplier_qava = sup.supplier_id_qava
LEFT JOIN supc_cte AS supc
ON supc.id_supplier_ekuep = sup.supplier_id_ekuep
WHERE _fivetran_deleted = 0
Right so what was your question again?
you want to get rid of all the nulls... if this is so "why so many left joins" or returning null from CASE statements..
Right so in the picture to show a waybill_no with values, and another where supplier_id_qava is null, given the later comes from
LEFT JOIN sup_cte AS sup
ON wbd.WAYBILL_ID = sup.WAYBILL_ID
and everything else connect via sup you should change that from a LEFT JOIN to just a JOIN

How to return 1 row instead of 3 when one column has different data

I have 3 rows of data returned from a query
OrderId | OtherId
--------+---------
1234 | 444
1234 | 555
1234 | 666
How to return data in this format
OrderId | OtherId | OtherId2 | OtherId
--------+---------+----------+--------
1234 | 444 | 555 | 666
Can I use Distinct for this problem?
EDIT
The result set comes from a query such as
left join (
Select distinct
o.id
,OL2.db
,case
when i.cust = 'cust2' then
case
when
lower(pdf.dept) not like 'abc%' or pdf.dept is null
then 'Yes'
else'No'
end
else 'Yes'
end as 'Show'
,otherId
from order o with(nolock)
Join instance i with(nolock) on i.id = o.id
Join orderLine ol with(nolock) on ol.id = o.SocialNetworker_Order_InstanceId
and ol.id = o.id
join product p with(nolock) on o.id = p.id
and ol.id = p.id
left join productEx pdf with(nolock) on p.id = pdf.id
and o.id = pdf.id
Where i.cust in ('cust1')
) ol2 on OL2.id = sno.id
and OL2.id2 = sno.id2
and i.db = cc.db
How to work solution into the above code?
You can use row_number() and conditional aggregation:
select orderid,
max(case when seqnum = 1 then otherid end) as otherid_1,
max(case when seqnum = 2 then otherid end) as otherid_2,
max(case when seqnum = 3 then otherid end) as otherid_3
from (select t.*, row_number() over (partition by orderid order by otherid) as seqnum
from t
) t
group by orderid;
Use an outer join with cascading join conditions:
select t1.OrderId, t1.OtherId OtherId1, t2.OtherId OtherId2, t3.OtherId OtherId3
from orders t1
left join orders t2 on t2.OrderId = t1.OrderId
and t2.OtherId > t1.OtherId
left join orders t3 on t3.OrderId = t2.OrderId
and t3.OtherId > t2.OtherId
If there are less than 3 other ids, the right-most columns will be null.
This query will work on pretty much any database.

Is multiple left join is better and faster with same table ?

SELECT
E.Id,
E.Name,
CASE EL.Application_Level WHEN 33 then 1 ELSE 0 END As MyDisplayName,
CASE EL1.Application_Level WHEN 34 then 1 ELSE 0 END As FoodTag
FROM
Entity E
INNER JOIN dbo.Countries CN ON cn.id=E.COUNTRY_ID
LEFT JOIN dbo.Entity_Levels EL ON E.ID = EL.Entity_ID AND EL.Application_Level = 33
LEFT JOIN dbo.Entity_Levels EL1 ON E.ID = EL1.Entity_ID AND EL1.Application_Level = 34
Instead of two join with same table i want to use OR Condition, becasue there will be more application levels added and i dont want to do add more joins.
Is there anyway i can use or condition and one join and merge multiple records to one record.
Since you don't show any sample data, this is only a guess, but it looks like you could do something like this with only 1 join to the ENTITY_LEVELS table:
SELECT
E.Id,
max(E.Name) as Name,
max(case when EL.application_level = 33 then 1 else 0 end) as MyDisplayName,
max(case when EL.application_level = 34 then 1 else 0 end) as FoodTag,
max(case when EL.application_level = 35 then 1 else 0 end) as RandomOtherThing
from entity E
INNER JOIN dbo.Countries CN ON cn.id=E.COUNTRY_ID
LEFT JOIN dbo.Entity_Levels EL ON E.ID = EL.Entity_ID
group by E.Id
SELECT E.Id
,E.Name
,CASE WHEN EL.Application_Level = 33
THEN 1
ELSE 0
END AS MyDisplayName
,CASE WHEN EL.Application_Level = 34
THEN 1
ELSE 0
END AS FoodTag
FROM Entity E WITH(NOLOCK)
INNER JOIN dbo.Countries CN WITH(NOLOCK) ON CN.id=E.COUNTRY_ID
LEFT JOIN dbo.Entity_Levels EL WITH(NOLOCK) ON E.ID=EL.Entity_ID

Nested Oracle SQL - Multiple Values

I have a table structure like:
Table = contact
Name Emailaddress ID
Bill bill#abc.com 1
James james#abc.com 2
Gill gill#abc.com 3
Table = contactrole
ContactID Role
1 11
1 12
1 13
2 11
2 12
3 12
I want to select the Name and Email address from the first table where the person has Role 12 but not 11 or 13. In this example it should return only Gill.
I believe I need a nested SELECT but having difficulty in doing this. I did the below but obviously it isn't working and returning everything.
SELECT c.Name, c.Emailaddress FROM contact c
WHERE (SELECT count(*) FROM contactrole cr
c.ID = cr.ContactID
AND cr.Role NOT IN (11, 13)
AND cr.Role IN (12)) > 0
You can use a combination of EXISTS and NOT EXISTS
SELECT *
FROM contact c
WHERE
EXISTS(SELECT 1 FROM contactrole cr WHERE cr.ContactID = c.ID AND cr.Role = 12)
AND NOT EXISTS(SELECT 1 FROM contactrole cr WHERE cr.ContactID = c.ID AND cr.Role IN(11, 13))
Another option is to use GROUP BY and HAVING:
SELECT c.*
FROM contact c
INNER JOIN contactrole cr
ON cr.ContactID = c.ID
GROUP BY
c.ID, c.Name, c.Emailaddress
HAVING
SUM(CASE WHEN cr.Role = 12 THEN 1 ELSE 0 END) > 0
AND SUM(CASE WHEN cr.Role IN(11, 13) THEN 1 ELSE 0 END) = 0
Use conditional aggregation in Having clause to filter the records
Try this
SELECT c.NAME,
c.emailaddress
FROM contact c
WHERE id IN (SELECT contactid
FROM contactrole
GROUP BY contactid
HAVING Count(CASE WHEN role = 12 THEN 1 END) > 1
AND Count(CASE WHEN role in (11,13) THEN 1 END) = 0)
If you have only 11,12,13 in role then use can use this
SELECT c.NAME,
c.emailaddress
FROM contact c
WHERE id IN (SELECT contactid
FROM contactrole
GROUP BY contactid
HAVING Count(CASE WHEN role = 12 THEN 1 END) = count(*)
You can do this using JOINs:
SELECT c.*
FROM CONTACT c
INNER JOIN CONTACTROLE cr12
ON cr12.CONTACTID = c.ID AND
cr12.ROLE = 12
LEFT OUTER JOIN CONTACTROLE cr11
ON cr11.CONTACTID = c.ID AND
cr11.ROLE = 11
LEFT OUTER JOIN CONTRACTROLE cr13
ON cr13.CONTACTID = c.ID AND
cr13.ROLE = 13
WHERE cr11.ROLE IS NULL AND
cr13.ROLE IS NULL
The INNER JOIN CONTACTROLE cr12 requires that role 12 exist for the given contact ID; the LEFT OUTER JOIN CONTACTROLE cr11 and LEFT OUTER JOIN CONTRACTROLE cr13 check to see if roles 11 and 13 might exist for the given contact ID; and the WHERE clause verifies that neither roles 11 or 13 exist.
Best of luck.

sql query with percent and aggregation functions

I'm trying to write a sql query where I need number of scores > 3 by county, then for counties on that list I need to produce a percentage of rooms with scores < 3. So I need three columns, County Name, # of scores > 3 by county, % of rooms with scores < 3 by county
SELECT County = c.Description, [Score > 3] = count(s.Score),
((select count(room.Name) where s.Score< 3) /( select count(room.Name) ) * 100)
FROM Sites AS s
inner join Profiles as p on s.Profile_Id = p.Id
inner join Counties as c on p.County_Id = c.Id
inner join Rooms as room on s.Id = room.Site_Id
where s.Score > 3
Group By c.Description
I think you are over complicating the issue, rather than subselects you can just limit the data returned by using the HAVING clause, then use CASE in the COUNT:
SELECT County = c.Description,
[Score > 3] = COUNT(CASE WHEN Sites.Score > 3 THEN 1 END),
[% Score < 3] = 100.0 * COUNT(CASE WHEN Sites.Score < 3 THEN 1 END) / COUNT(1)
FROM Sites
INNER JOIN Profiles
ON Sites.Profile_Id = Profiles.Id
INNER JOIN Counties
ON Profiles.County_Id = Counties.Id
INNER JOIN Rooms
ON Sites.Id = Rooms.Site_Id
GROUP BY c.Description
HAVING COUNT(CASE WHEN Sites.Score > 3 THEN 1 END) > 0;
Demo on SQL Fiddle
EDIT
SELECT County = c.Description,
[Score > 3] = COUNT(CASE WHEN Sites.Score > 3 THEN 1 END),
[% Score < 3] = 100.0 * SUM(CASE WHEN Sites.Score < 3 THEN 1 END) / COUNT(*),
[Score > 3] = SUM(CASE WHEN Sites.Score > 3 THEN RoomCount ELSE 0 END),
[% Score < 3] = 100.0 * SUM(CASE WHEN Sites.Score < 3 THEN RoomCount ELSE 0 END) / SUM(RoomCount)
FROM Sites
INNER JOIN Profiles
ON Sites.Profile_Id = Profiles.Id
INNER JOIN Counties
ON Profiles.County_Id = Counties.Id
INNER JOIN
( SELECT Site_Id, RoomCount = COUNT(*)
FROM Rooms
GROUP BY Site_Id
) Rooms
ON Sites.Id = Rooms.Site_Id
GROUP BY c.Description
HAVING COUNT(CASE WHEN Sites.Score > 3 THEN 1 END) > 0;
Use Cast
SELECT County = c.Description, [Score > 3] = count(s.Score),
( Cast(select count(room.Name) where s.Score < 3 ) as float / ( select count(room.Name) ) * 100)
FROM Sites AS s
inner join Profiles as p on s.Profile_Id = p.Id
inner join Counties as c on p.County_Id = c.Id
inner join Rooms as room on s.Id = room.Site_Id
where s.Score > 3
Group By c.Description
[Score > 3] = count(s.Score)
...
where s.Score > 3
Both statements are not needed. In fact your Where clause limits all operations to s.score >3, which is not ideal when you are also trying to pull data from scores <3.
If you are trying to count both the cases where s.Score>3 and where it is <3, you need to use the CASE statement
SELECT SUM(CASE WHEN s.score < 3 THEN 1 ELSE 0 END) AS Hiscores,
SUM(CASE WHEN s.score > 3 THEN 1 ELSE 0 END) /count(s.scores) AS percentLowScores
This should do it
SELECT c.Description County,
SUM(CASE WHEN s.score < 3 THEN 1 ELSE 0 END) AS Hiscores,
SUM(CASE WHEN s.score > 3 THEN 1 ELSE 0 END) /count(s.scores) AS percentLowScores
FROM Sites AS s
inner join Profiles as p on s.Profile_Id = p.Id
inner join Counties as c on p.County_Id = c.Id
inner join Rooms as room on s.Id = room.Site_Id
Group By c.Description