Sql查询找到他之前没买过的新产品的零售商

时间:2018-04-22 19:39:16

标签: sql oracle

要求:我有2组数据。 数据集1:所有在3周内购买不同商品的零售商 数据集2:所有在12周内购买不同商品的零售商

我想选择第1组的零售商,他们购买了他在12周窗口内没有购买过的新产品。

我开发了以下代码,但没有产生所需的结果。请帮忙

 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;

数据集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

数据集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

结果:

RETAILER_CD INV_NO  DOC_DT  SLS_ACT ITM_CD
R1            1    1/4/2018   10     P1
R1            1    1/4/2018   10     P2

由于数据集1中的INV_NO 1已获得零售商未在90天内购买的ITM_CD P2,我想选择此发票详情。

2 个答案:

答案 0 :(得分:0)

我试图逐步建立它以便更好地理解:

第一步

找到在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
;

现代左联 -

这里是一个现代的Left-join,没有假表,以便更好地进行概述

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

第二步

查找从dataset1到所选项目的完整订单。

* 2a缩短选择

将选择缩短为所需的值

SELECT dataset1.inv_no
  FROM dataset1
       LEFT JOIN dataset2
           ON dataset1.itm_cd = dataset2.itm_cd AND dataset2.itm_cd IS NULL;

* 2b

将invoice-nos插入表格:

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

答案 1 :(得分:0)

原始请求“让他们在set2中购买了他们没有在set2中购买的商品的零售商”很容易让人感到羞耻:

select distinct retailer_cd
from set1
where (retailer_cd, itm_cd) not in (select retailer_cd, itm_cd from set2);

但是现在您已经添加了预期结果,并希望获得发生此类购买的完整发票,而不仅仅是列出零售商。一种方法是先购买,然后在下一步中使用另一个IN条款获取整个发票:

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)
);