具有子查询和多个group by语句的DB2查询

时间:2019-01-25 03:11:10

标签: sql db2 subquery

我有一个包含多个子查询和条件的查询,以建立各自具有自己分组的计算列。

问题是,某项未正确加入或未正确分组,我无法在所有行中获得正确的值。我选择了过去90天的原始行,但我的计算仅基于过去30天的记录。

SELECT
  t.dealer,
  t.rep,
  t.group,
  t.dtl1,
  t.dtl2,
  t.quant,
  temp.sales as V1,
  tmng.sales as V2,
  tall.sales as V3
FROM
     products t
    left outer JOIN (
        SELECT dealer,group,dtl1,dtl2, SUM(cast(quant as int)) as sales
        FROM products
        WHERE last_ship_date > CURRENT_DATE - 30 DAYS
        GROUP BY dealer,group,dtl1,dtl2
    ) temp ON temp.dealer = t.dealer and temp.group = t.group and temp.dtl1 = t.dtl1 and temp.dtl2 = t.dtl2
    left outer JOIN (
        SELECT sales_rep, group,dtl1,dtl2, SUM(cast(quant as int)) as sales
        FROM products
        WHERE last_ship_date > CURRENT_DATE - 30 DAYS
        GROUP BY sales_rep,group,dtl1,dtl2
    ) tmng ON  tmng.sales_rep = t.sales_rep AND tmng.group = t.group AND tmng.dtl1 = t.dtl1 and tmng.dtl2 = t.dtl2
    left outer JOIN (
        SELECT dealer, sales_rep, group,dtl1,dtl2,SUM(cast(quant as int)) as sales
        FROM products
        WHERE last_ship_date > CURRENT_DATE - 30 DAYS
        group by dealer,sales_rep, group,dtl1,dtl2
    ) tall on tall.dealer = t.dealer and tall.sales_rep = t.sales_rep and  tall.group = t.group and tall.dtl1 = t.dtl1 and tall.dtl2 = t.dtl2

WHERE t.last_ship_date > CURRENT_DATE - 90 DAYS;

这个想法是,一个产品在Group / Dtl1 / Dtl2中是唯一的。因此,如果我查询单个产品(具有该唯一组合),则可以得到每行的特定总数量,但是我需要解决的是我的最后三列,其中我需要最近30天的“数量”总和经销商,代表和总数。

现在,我得到的行数正确,但是最后三列中的行值和空值不正确。

Dealer | Rep   | Group  | Dtl1   | Dtl2 | qty |   V1  |   V2    |  V3
========================================================================
21177  |  165  |  4867  |  2878  |  29  |  1  |  null  |  null  |  null
19445  |  182  |  4867  |  2878  |  29  |  1  |  null  |  null  |  null
20949  |  340  |  4867  |  2878  |  29  |  2  |  null  |  null  |  null
21347  |  353  |  4867  |  2878  |  29  |  1  |  null  |  null  |  null
23068  |  353  |  4867  |  2878  |  29  |  1  |  null  |  null  |  null
17195  |  353  |  4867  |  2878  |  29  |  6  |  null  |  null  |  null
23040  |  353  |  4867  |  2878  |  29  |  1  |  null  |  null  |  null
5620   |  380  |  4867  |  2878  |  29  |  4  |  null  |  null  |  null
23009  |  380  |  4867  |  2878  |  29  |  3  |  null  |  null  |  null
13529  |  390  |  4867  |  2878  |  29  |  1  |  null  |  null  |  null
22706  |  394  |  4867  |  2878  |  29  |  1  |  1     |  1     |  1
17049  |  394  |  4867  |  2878  |  29  |  4  |  1     | null   | null 
17879  |  397  |  4867  |  2878  |  29  |  1  |  null  |  null  |  null
21320  |  445  |  4867  |  2878  |  29  |  1  |  null  |  null  |  null
21231  |  457  |  4867  |  2878  |  29  |  1  |  1     |  1     |  1

我想要得到的是这个

Dealer | Rep   | Group  | Dtl1   | Dtl2 | qty | V1  | V2  |  V3
================================================================
21177  |  165  |  4867  |  2878  |  29  |  1  |  1  |  1  |  29
19445  |  182  |  4867  |  2878  |  29  |  1  |  1  |  1  |  29
20949  |  340  |  4867  |  2878  |  29  |  2  |  2  |  2  |  29
21347  |  353  |  4867  |  2878  |  29  |  1  |  1  |  9  |  29
23068  |  353  |  4867  |  2878  |  29  |  1  |  1  |  9  |  29
17195  |  353  |  4867  |  2878  |  29  |  6  |  6  |  9  |  29
23040  |  353  |  4867  |  2878  |  29  |  1  |  1  |  9  |  29
5620   |  380  |  4867  |  2878  |  29  |  4  |  4  |  7  |  29
23009  |  380  |  4867  |  2878  |  29  |  3  |  3  |  7  |  29
13529  |  390  |  4867  |  2878  |  29  |  1  |  1  |  1  |  29
22706  |  394  |  4867  |  2878  |  29  |  1  |  1  |  5  |  29
17049  |  394  |  4867  |  2878  |  29  |  4  |  4  |  5  |  29 
17879  |  397  |  4867  |  2878  |  29  |  1  |  1  |  1  |  29
21320  |  445  |  4867  |  2878  |  29  |  1  |  1  |  1  |  29
21231  |  457  |  4867  |  2878  |  29  |  1  |  1  |  1  |  29

因此,V1是最近30天的Dealer / group / dtl1 / dtl2的数量之和,V2是最近30天的Rep / Group / Dtl1 / Dtl2的数量之和,V3是最近30天该Group / Dtl1 / Dtl2的总计(数量)。

我为什么错了?

这是小提琴:http://www.sqlfiddle.com/#!9/22251a

1 个答案:

答案 0 :(得分:1)

尝试一下:

WITH T (DEALER, REP, GROUP, DTL1, Dtl2, QUANT, LAST_SHIP_DATE) AS (
VALUES  (21177, 165, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY),
        (19445, 182, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY),
        (20949, 340, 4867, 2878, 29, 2, CURRENT DATE - 10 DAY),
        (21347, 353, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY),
        (23068, 353, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY),
        (17195, 353, 4867, 2878, 29, 6, CURRENT DATE - 10 DAY),
        (23040, 353, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY),
        (5620,  380, 4867, 2878, 29, 4, CURRENT DATE - 10 DAY),
        (23009, 380, 4867, 2878, 29, 3, CURRENT DATE - 10 DAY),
        (13529, 390, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY),
        (22706, 394, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY),
        (17049, 394, 4867, 2878, 29, 4, CURRENT DATE - 10 DAY),
        (17879, 397, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY),
        (21320, 445, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY),
        (21231, 457, 4867, 2878, 29, 1, CURRENT DATE - 10 DAY)
      , (1, 1, 4867, 2878, 29, 1, CURRENT DATE - 100 DAY)
)
SELECT T.DEALER, T.REP, T.GROUP, T.DTL1, T.Dtl2, T.QUANT
/*
, SUM(CASE WHEN last_ship_date > CURRENT_DATE - 30 DAYS THEN QUANT END) OVER(PARTITION BY DEALER, GROUP, DTL1, Dtl2) V1
, SUM(CASE WHEN last_ship_date > CURRENT_DATE - 30 DAYS THEN QUANT END) OVER(PARTITION BY REP,    GROUP, DTL1, Dtl2) V2
, SUM(CASE WHEN last_ship_date > CURRENT_DATE - 30 DAYS THEN QUANT END) OVER(PARTITION BY         GROUP, DTL1, Dtl2) V3
FROM T;
*/
, COALESCE(T1.V1, 0) V1, COALESCE(T2.V2, 0) V2, COALESCE(T3.V3, 0) V3
FROM T
LEFT JOIN (
SELECT DEALER, GROUP, DTL1, Dtl2, SUM(QUANT) V1
FROM T
WHERE last_ship_date > CURRENT_DATE - 30 DAYS
GROUP BY DEALER, GROUP, DTL1, Dtl2
) T1 ON T1.DEALER=T.DEALER AND T1.GROUP=T.GROUP AND T1.DTL1=T.DTL1 AND T1.DTL2=T.DTL2
LEFT JOIN (
SELECT REP, GROUP, DTL1, Dtl2, SUM(QUANT) V2
FROM T
WHERE last_ship_date > CURRENT_DATE - 30 DAYS
GROUP BY REP, GROUP, DTL1, Dtl2
) T2 ON T2.REP=T.REP AND T2.GROUP=T.GROUP AND T2.DTL1=T.DTL1 AND T2.DTL2=T.DTL2
LEFT JOIN (
SELECT GROUP, DTL1, Dtl2, SUM(QUANT) V3
FROM T
WHERE last_ship_date > CURRENT_DATE - 30 DAYS
GROUP BY GROUP, DTL1, Dtl2
) T3 ON T3.GROUP=T.GROUP AND T3.DTL1=T.DTL1 AND T3.DTL2=T.DTL2;