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
I have code which returns the last 5 results for any given ID (including the ID given). What i want is to return extra rows with the word none and 00 respectively if there aren't previous values to equal 5.
So if the code returns 3 results generate 2 extra rows, if the code returns 4 results generate 1 extra row.
Current Code: (aaa.FS01 = '12345') is just an example of an ID
SELECT aaa.FS01,
CAST(COUNT(distinct bbb.MG) AS FLOAT)/ convert(varchar(10), DATEDIFF(second ,MIN(TP), MAX(TP))/3600.0) TPDIFF,
22 TAG
FROM TableA aaa
INNER JOIN TableB bbb ON bbb.tpl = aaa.FS01 OR bbb.fpl = aaa.FS01
INNER JOIN TableC ccc ON ccc.id = aaa.FS01
INNER JOIN TableD ddd ON aaa.VG = ddd.gkey
WHERE aaa.FS01 IN (
SELECT TOP 5 ccc.id
FROM TableA aaa
INNER JOIN TableC ccc ON ccc.id = aaa.FS01
INNER JOIN TableD v ON aaa.VG = ddd.gkey
WHERE ddd.name = (SELECT ddd.name FROM TableA aaa
INNER JOIN TableD v ON aaa.VG = ddd.gkey WHERE aaa.FS01 = '12345')
ORDER BY ccc.ata DESC)
GROUP BY aaa.FS01, ccc.ata
ORDER BY ccc.ata DESC
Current Output (For an FS01 that only returns 3 values):
FS01 TPDIFF TAG
12345 30 22
22222 50 22
45122 90 22
Expected Output (For an FS01 that only returns 3 values):
FS01 TPDIFF TAG
12345 30 22
22222 50 22
45122 90 22
none 00 22
none 00 22
Current Output (For an FS01 that only returns 1 value):
FS01 TPDIFF TAG
74133 30 22
Expected Output (For an FS01 that only returns 1 value):
FS01 TPDIFF TAG
74133 80 22
none 00 22
none 00 22
none 00 22
none 00 22
You can do this with a single query:
with t as (<your query here>),
nones as (
select 'none' as FS01, '00' as TPDIFF, '22' as TAG
from (values (1), (2), (3), (4), (5))
)
select top (5) tn.FS01, tn.TPDIFF, tn.TAG
from ((select t.* from t) union all
nones
) tn
order by (case when FS01 = 'none' then 1 else 2 end) as asc;
I would declare a table variable like this. Then use a while to append empty rows.
Something like this:
DECLARE #tbl AS TABLE(FS01 text, TPDIFF text, TAG Text);
INSERT INTO #tbl (FS01, TPDIFF, TAG)
--your select statement (copied)
SELECT aaa.FS01,
CAST(COUNT(distinct bbb.MG) AS FLOAT)/ convert(varchar(10), DATEDIFF(second ,MIN(TP), MAX(TP))/3600.0) TPDIFF,
22 TAG
FROM TableA aaa
INNER JOIN TableB bbb ON bbb.tpl = aaa.FS01 OR bbb.fpl = aaa.FS01
INNER JOIN TableC ccc ON ccc.id = aaa.FS01
INNER JOIN TableD ddd ON aaa.VG = ddd.gkey
WHERE aaa.FS01 IN (
SELECT TOP 5 ccc.id
FROM TableA aaa
INNER JOIN TableC ccc ON ccc.id = aaa.FS01
INNER JOIN TableD v ON aaa.VG = ddd.gkey
WHERE ddd.name = (SELECT ddd.name FROM TableA aaa
INNER JOIN TableD v ON aaa.VG = ddd.gkey WHERE aaa.FS01 = '12345')
ORDER BY ccc.ata DESC)
GROUP BY aaa.FS01, ccc.ata
ORDER BY ccc.ata DESC
declare #cnt as int;
SELECT #cnt = count(*) from #tbl
while #cnt < 5
BEGIN
insert into #tbl (FS01, TPDIFF, TAG) VALUES('none', '00', '22');
select #cnt = #cnt+1;
end
select top 5 * from #tbl;
I have two tables
T1:
ID, Truck, Trailer
1 null null
2 null null
T2:
ID, Type, ResourceID
1 R 111
1 F 222
1 D 333
2 R 444
2 F 555
I need a result where
ID, Truck, Trailer
1 111 222
2 444 555
How can I update T1.Truck = T2.ResourceID when T2.Type = R and T1.Trailer = T2.ResourceID when T2.Type = F where T1.ID = T2.ID.
This is what I have so far
UPDATE T1
SET T1.Truck = CASE
WHEN T2.Type = 'R' THEN T2.ResourceId
ELSE T1.Truck
END,
T1.Trailer = CASE
WHEN T2.Type = 'F' THEN T2.ResourceId
ELSE T1.Trailer
END
FROM T1 INNER JOIN (SELECT Id, Type, ResourceId
FROM T2) T2
ON T1.Id = T2.Id
This will only Truck, but not trailer.
What am I missing?
The problem with your current update query is that the update will update one column to null as it can't match both conditions at the same time.
If you did a select * instead of the update the result would look like:
ID Truck Trailer Id Type ResourceId
1 NULL NULL 1 R 111 -- this will set R = 111 and F = null
1 NULL NULL 1 F 222 -- this will set F = 222 and R = null
1 NULL NULL 1 D 333 -- this will set R = null and F = null
2 NULL NULL 2 R 444 -- this will set R = 444 and F = null
2 NULL NULL 2 F 555 -- this will set R = null and F = 555
Here you can see that when Type matches R the update for F will update to null et cetera.
One solution is to join the T2 table twice:
UPDATE T1
SET
T1.Truck = T2.ResourceId
,
T1.Trailer = T3.ResourceId
FROM T1
INNER JOIN (SELECT Id, ResourceId FROM T2 WHERE Type = 'R') T2 ON T1.Id = T2.Id
INNER JOIN (SELECT Id, ResourceId FROM T2 WHERE Type = 'F') T3 ON T1.Id = T3.Id
If there might not always be both types (R,F) then use left join instead of inner join and check for null values.
Edit: thinking a bit more gives this query:
UPDATE T1
SET
T1.Truck = ISNULL(T.rValue, T1.Truck),
T1.Trailer = ISNULL(T.fValue, T1.Trailer)
FROM T1
INNER JOIN (
SELECT
Id,
rValue = MAX(CASE WHEN Type = 'R' THEN ResourceId END),
fValue = MAX(CASE WHEN Type = 'F' THEN ResourceId END)
FROM T2 GROUP BY id
) T ON T1.Id = T.Id
On a side note: using an alias for a derived table that is also a table name can be pretty confusing and should be avoided.
you can PIVOT the table t2 before updating the t1 table
Use the following query to pivot the t2 table.
SELECT ID, R, F
FROM t2
PIVOT (Max(resourceID)
FOR type IN ([R],[F]))pv
Now the result will in the format of t1 table you can easily update using the following query
UPDATE A
SET Trailer = F,
Truck = R
FROM t1 A
INNER JOIN (SELECT ID, R, F
FROM t2
PIVOT (Max(resourceID)
FOR type IN ([R],
[F]))pv) B
ON A.ID = b.ID
SQLFIDDLE DEMO
You can use a JOIN with a condition for each case, so you would JOIN to T2 twice. First on the Id and [Type] = 'R' and again, with [Type] = 'F'.
Here's some runnable sample code:
CREATE TABLE #t1 (id INT, Truck INT, Trailer int)
CREATE TABLE #t2 (id INT, [Type] VARCHAR(1), ResourceId int)
INSERT INTO #t1
( id, Truck, Trailer )
VALUES (1, NULL, NULL),
(2, NULL, NULL)
INSERT INTO #t2
( id, [Type], ResourceId )
VALUES ( 1, 'R', 111),
( 1, 'F', 222),
( 1, 'D', 333),
( 2, 'R', 444),
( 2, 'F', 555)
UPDATE #t1
SET Truck = TR.ResourceId, Trailer = TF.ResourceId
FROM #t1
INNER JOIN #t2 AS TR ON TR.id = #t1.id AND TR.[Type] = 'R'
INNER JOIN #t2 AS TF ON TF.id = #t1.id AND TF.[Type] = 'F'
SELECT * FROM #t1
DROP TABLE #t1
DROP TABLE #t2