Requirement: I got 2 sets of data. Data set 1: All The retailers who purchased different items in the 3 weeks Data set 2: All The retailers who purchased different items in the 12 weeks
I would like to pick the retailers from set 1 who bought a new product which he has not bought in the 12 weeks window.
I have developed the following code which is not yielding required results. Please help
SELECT RC.RETAILER_CD,
RC.INV_NO,
RC.DOC_DT,
SUM (RC.SLS_ACT)
FROM RANGE_CREATION RC, ACTIVITY_TXN AV
WHERE RC.DOC_DT > ACTIVITY_START_DT
AND RC.DOC_DT <= ACTIVITY_CLOSURE_DT + 14
AND RC.RETAILER_CD = AV.CHANNEL_NAME
AND AV.TYPE = 'Range Expansion'
AND EXISTS
(SELECT RC1.RETAILER_CD, RC1.INV_NO, RC1.DOC_DT
FROM RANGE_CREATION RC1, ACTIVITY_TXN AV1
WHERE RC1.RETAILER_CD = RC.RETAILER_CD
AND RC1.RETAILER_CD = AV1.CHANNEL_NAME
AND RC1.DOC_DT > AV1.ACTIVITY_START_DT - 90
AND DOC_DT < ACTIVITY_START_DT
--AND RC1.INV_NO <> RC.INV_NO
AND RC1.ITM_CD <> RC.ITM_CD
AND AV1.TYPE = 'Range Expansion')
GROUP BY RC.RETAILER_CD, RC.INV_NO, RC.DOC_DT
HAVING SUM (RC.SLS_ACT) > 50
ORDER BY RC.RETAILER_CD, RC.INV_NO, RC.DOC_DT;
Data Set 1:
RETAILER_CD INV_NO DOC_DT SLS_ACT ITM_CD
R1 1 1/4/2018 10 P1
R1 1 1/4/2018 10 P2
R1 2 31/3/2018 10 P1
Data Set 2:
RETAILER_CD INV_NO DOC_DT SLS_ACT ITM_CD
R1 9 1/2/2018 10 P1
R1 10 2/2/2018 11 P1
R1 11 29/1/2018 12 P3
R1 12 30/1/2018 13 P4
R1 13 31/1/2018 14 P5
Result:
RETAILER_CD INV_NO DOC_DT SLS_ACT ITM_CD
R1 1 1/4/2018 10 P1
R1 1 1/4/2018 10 P2
As the INV_NO 1 from Data Set-1 has got ITM_CD P2 which the retailer hasn't bought in the 90 days period, I want to pick this invoice details.
I tried to build it step-by-step for a better understanding:
Find the item, which is not found in dataset2
select dataset1.itm_cd, dataset1.inv_no, dataset2.inv_no from
(
select 'R1' as Retailer_cd, 1 as inv_no, 10 as sls_act, 'P1' as itm_cd from dual union all
select 'R1' as Retailer_cd, 1 as inv_no, 10 as sls_act, 'P2' as itm_cd from dual union all
select 'R1' as Retailer_cd, 2 as inv_no, 10 as sls_act, 'P1' as itm_cd from dual
) dataset1, -- faketable1
(
select 'R1' as Retailer_cd, 9 as inv_no, 10 as sls_act, 'P1' as itm_cd from dual union all
select 'R1' as Retailer_cd, 10 as inv_no, 11 as sls_act, 'P1' as itm_cd from dual union all
select 'R1' as Retailer_cd, 11 as inv_no, 12 as sls_act, 'P3' as itm_cd from dual union all
select 'R1' as Retailer_cd, 12 as inv_no, 13 as sls_act, 'P4' as itm_cd from dual union all
select 'R1' as Retailer_cd, 13 as inv_no, 14 as sls_act, 'P5' as itm_cd from dual
) dataset2 -- faketable2
where 1=1
AND dataset1.itm_cd = dataset2.itm_cd (+) -- Left join -> when right table not found, row is shown anyway
AND dataset2.itm_cd is null -- only rows from dataset1 when no row in dataset2
;
Here a modern Left-join without the fake-tables for better overview
SELECT dataset1.itm_cd, dataset1.inv_no, dataset2.inv_no
FROM dataset1
LEFT JOIN dataset2
ON dataset1.itm_cd = dataset2.itm_cd AND dataset2.itm_cd IS NULL
WHERE 1=1; -- no where-condition needed
Find the complete order from dataset1 to the selected item.
Shorten the select to the needed values
SELECT dataset1.inv_no
FROM dataset1
LEFT JOIN dataset2
ON dataset1.itm_cd = dataset2.itm_cd AND dataset2.itm_cd IS NULL;
Insert invoice-nos as table:
SELECT r.*
FROM dataset1 r, -- this will be out output
(SELECT distinct dataset1.inv_no -- added a distinct -> if two items in one invoice aren't bought in 90 days the inv_no will only be shown once.
FROM dataset1, dataset2
WHERE 1 = 1
AND dataset1.itm_cd = dataset2.itm_cd(+)
AND dataset2.itm_cd IS NULL) selectedItems -- this is the list of inv_nos
WHERE selectedItems.INV_NO = dataset1.inv_no
The original request "get retailers that bought an item in set1 they didn't buy in set2" is easy peasy:
select distinct retailer_cd
from set1
where (retailer_cd, itm_cd) not in (select retailer_cd, itm_cd from set2);
But now you have added expected results and want the complete invoices where such purchases occur, instead of merely listing the retailers. One way is to get the purchase first and then get the whole invoice in the next step with another IN
clause:
select *
from set1
where (retailer_cd, inv_no) in
(
select retailer_cd, inv_no
from set1
where (retailer_cd, itm_cd) not in (select retailer_cd, itm_cd from set2)
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.