按日期和编号分组合并数据以创建新列

Posted

技术标签:

【中文标题】按日期和编号分组合并数据以创建新列【英文标题】:Group by Date and Num for Merged Data to Create new Column 【发布时间】:2017-11-20 19:12:19 【问题描述】:

我是 SQL 的初学者,想按日期/编号对连接数据进行分组以创建新列。我拉取后的数据如下所示:

select
    items.A,
    items.B,
    items.C,
    items.NUM,
    items.E,
    source.QTY,
    dates.DATE
from original_metric source
inner join grocery items
    on items.id = source.item_id
inner join day_dates dates
    on dates.date_id = source.date_id;

    A        B     C   NUM   E    QTY    DATE       
Vegetable carrot  John  1  Main   14  26-APR-11
Vegetable carrot  John  1  Main   35  27-APR-11
Vegetable carrot  John  1  Main    2  21-SEP-15
Vegetable carrot  John  1  Main   11  23-APR-17
Vegetable carrot  John  1  Main   25  22-MAY-17
Vegetable carrot  John  1  Main   20  20-APR-18
Vegetable onion   John  2  Extra  23  02-AUG-16
Vegetable onion   John  2  Extra  32  07-AUG-16
Meat      pork    Jane  3  Main   10  02-AUG-16
Meat      pork    Jane  3  Main   60  19-JAN-17
Meat      pork    Jane  3  Main   12  25-DEC-17

我希望它是什么样子:

   A         B      C  NUM   E    QTY         DATE           QTR      WEEK_FILL    CURRENT_FILL 
Vegetable carrot  John  1  Main   49  24-APR-11:30-APR-11  2011Q4   none         100%
Vegetable carrot  John  1  Main    2  20-SEP-15:15-SEP-15  2015Q2   none         100% 
Vegetable carrot  John  1  Main   11  23-APR-17:29-APR-17  2017Q4   22.4%        73.4%
Vegetable carrot  John  1  Main   25  21-MAY-17:27-MAY-17  2017Q4   51%          73.4% 
Vegetable carrot  John  1  Main   20  15-APR-18:21-APR-18  2018Q4   80%          80% 
Vegetable onion   John  2  Extra  55  31-JUL-16:07-AUG-16  2016Q1   none         100%
Meat      pork    Jane  3  Main   10  31-JUL-16:07-AUG-16  2016Q1   none         100%
Meat      pork    Jane  3  Main   60  15-JAN-17:21-JAN-17  2017Q3   none         100%
Meat      pork    Jane  3  Main   12  24-DEC-17:30-DEC-17  2017Q3   none         100%

我想按周按 NUM 对数量进行分组。然后根据 DATE,显示它属于哪个 QTR。

然后,对于 WEEK_FILL,我试图合并以下逻辑:数量(在该周)除以总和(上一年同一季度的所有数量)除以 NUM。如果没有上一年,则往前追溯,直到有匹配的季度。否则,如果没有前几年,则将其保留为“无”。

然后,对于 CURRENT_FILL,我尝试加入类似的逻辑: 总和(该季度的所有数量)除以总和(上一年同一季度的所有数量)除以 NUM。如果没有上一年,则往前追溯,直到有匹配的季度。否则,如果没有前几年,则将其保留为 100%。

(供参考,财政日历Q1:6月、7月、8月;Q2:9月、10月、11月;Q3:12月、1月、2月;4季度:3月、4月、5月)

【问题讨论】:

DATA 在您的预期输出中似乎有误。日期范围应为一周中的第一天到最后一天。请更正第一个。 对不起,我相信我对你的意思感到困惑。日期结构当前为 dd-MONTH-yy:dd-MONTH-yy,对于预期输出的第一行,2011 年 4 月 26 日和 27 日都在 24-APR-11:30-APR-11 之间 约翰的两个洋葱怎么了? 两条洋葱线(数量 23+32=>55)被归为一组,因为这两个日期在同一周内。 【参考方案1】:

试试这个查询

WITH dataCTE AS(
  SELECT
    q.*,
    DENSE_RANK()OVER(PARTITION BY q.NUM,q.Q ORDER BY q.Y) Y_ORDER
  FROM
    (
      SELECT
        d.*,
        EXTRACT(YEAR FROM DT) Y,
        -- Q1: JUN, JUL, AUG; Q2: SEP, OCT, NOV; Q3: DEC, JAN, FEB; Q4: MAR, APR, MAY
        DECODE(EXTRACT(MONTH FROM DT),6,1,7,1,8,1,9,2,10,2,11,2,12,3,1,3,2,3,3,4,4,4,5,4) Q
      FROM TEST_DATA d
    ) q
)    
SELECT
  d.*,
  Y||'Q'||Q QTR,
  NVL(TO_CHAR(100*d.QTY/
    (
      SELECT SUM(p.QTY)
      FROM dataCTE p
      WHERE p.Y_ORDER=d.Y_ORDER-1
        AND p.Q=d.Q
        AND p.NUM=d.NUM
    ),'9999.99'),'none') WEEK_FILL,
  NVL(100*SUM(d.QTY)OVER(PARTITION BY d.Y,d.Q ORDER BY d.DT RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)/
    (
      SELECT SUM(p.QTY)
      FROM dataCTE p
      WHERE p.Y_ORDER=d.Y_ORDER-1
        AND p.Q=d.Q
        AND p.NUM=d.NUM
    ),100) CURRENT_FILL
FROM dataCTE d

第二个变种

WITH dataCTE AS(
  SELECT
    q.*,
    DENSE_RANK()OVER(PARTITION BY q.NUM,q.Q ORDER BY q.Y) Y_ORDER
  FROM
    (
      SELECT
        d.*,
        EXTRACT(YEAR FROM DT) Y,
        -- Q1: JUN, JUL, AUG; Q2: SEP, OCT, NOV; Q3: DEC, JAN, FEB; Q4: MAR, APR, MAY
        DECODE(EXTRACT(MONTH FROM DT),6,1,7,1,8,1,9,2,10,2,11,2,12,3,1,3,2,3,3,4,4,4,5,4) Q
      FROM TEST_DATA d
    ) q
)
SELECT
  d.*,
  d.Y||'Q'||d.Q QTR,
  NVL(TO_CHAR(100*d.QTY/p.PREV_QTY,'9999.99'),'none') WEEK_FILL,
  NVL(100*SUM(d.QTY)OVER(PARTITION BY d.Y,d.Q ORDER BY d.DT RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)/
      p.PREV_QTY,100) CURRENT_FILL
FROM dataCTE d
LEFT JOIN
  (
    SELECT Y_ORDER,Q,NUM,SUM(QTY) PREV_QTY
    FROM dataCTE
    GROUP BY Y_ORDER,Q,NUM
  ) p
ON p.Y_ORDER=d.Y_ORDER-1 AND p.Q=d.Q AND p.NUM=d.NUM

TEST_DATA 是您的查询

CREATE TABLE TEST_DATA(
  A varchar2(20),
  B varchar2(20),
  C varchar2(20),
  NUM number,
  E varchar2(20),
  QTY number,
  DT date
);

INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Vegetable','carrot','John',1,'Main',14,'26-APR-11');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Vegetable','carrot','John',1,'Main',35,'27-APR-11');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Vegetable','carrot','John',1,'Main', 2,'21-SEP-15');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Vegetable','carrot','John',1,'Main',11,'23-APR-17');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Vegetable','carrot','John',1,'Main',25,'22-MAY-17');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Vegetable','carrot','John',1,'Main',20,'20-APR-18');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Vegetable','onion','John',2,'Extra',23,'02-AUG-16');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Vegetable','onion','John',2,'Extra',32,'07-AUG-16');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Meat','pork','Jane',3,'Main',10,'02-AUG-16');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Meat','pork','Jane',3,'Main',60,'19-JAN-17');
INSERT INTO TEST_DATA(A,B,C,NUM,E,QTY,DT)VALUES('Meat','pork','Jane',3,'Main',12,'25-DEC-17');

SQL 小提琴: 1 - http://sqlfiddle.com/#!4/e7eaa/49 2 - http://sqlfiddle.com/#!4/e7eaa/51

但我认为80% 换成2018Q4 是错误的,因为20/(11+25)=55.56

【讨论】:

以上是关于按日期和编号分组合并数据以创建新列的主要内容,如果未能解决你的问题,请参考以下文章

Python Pandas 使用日期时间数据按日期分组

Excel分组快速自动填充编号

使用 SQL 查询对新列进行分组和扩展?

按季度编号和名称分组的上一个 DAX 值

在 SQLAlchemy 中以特定格式按日期分组

按多列分组并将dict元素的中值作为熊猫中的新列