如何查询上周的每日库存数量

时间:2019-05-07 19:22:55

标签: sql oracle

我正在尝试编写一个查询,以查询过去7天(一周)的每天库存。这是查询:

select id, day, inventory
from tbl
where day >= DATEADD(day,-7, GETDATE())

产生此表:

id      day         inventory
1223    2019-05-01  1
1223    2019-05-02  5
412345  2019-05-02  3
412345  2019-05-03  1
12      2019-05-02  8
1234    2019-05-01  467
1234    2019-05-02  493

我不确定获得以下结果的最简单方法:

id      2019-05-01  2019-05-02  2019-05-03
1223    1           5
412345              3           1
12                  8
1234    467         493

1 个答案:

答案 0 :(得分:0)

由于不需要在返回中包含特定的列名,因此一种解决方法是使用PIVOT
PIVOT对于拥有静态存储区可能非常严格,因此此处的示例使用动态sql来移动7天的窗口。
这种方法有一些实际的缺点-动态sql,编译的对象,kludgy代码等。因此,我不愿实际推荐这种方法,但是使用动态sql可以向PIVOT提供静态存储区。
下面是使用您提供的表的示例。

此示例将汇总从提供的日期开始的为期7天的每一天ID的所有库存。 (默认为今天的前7天(今天除外)。

为了允许从SQL中调用此方法,此示例创建了一些数据传输对象以及一个函数,用于创建并返回为期7天的窗口。

示例数据:

CREATE TABLE TBL (ID INTEGER, DAY DATE, INVENTORY INTEGER);
INSERT INTO TBL VALUES (1223, DATE '2019-05-01', 1);
INSERT INTO TBL VALUES (1223, DATE '2019-05-02', 5);
INSERT INTO TBL VALUES (412345, DATE '2019-05-02', 3);
INSERT INTO TBL VALUES (412345, DATE '2019-05-03', 1);
INSERT INTO TBL VALUES (12, DATE '2019-05-02', 8);
INSERT INTO TBL VALUES (1234, DATE '2019-05-01', 467);
INSERT INTO TBL VALUES (1234, DATE '2019-05-02', 493);
COMMIT;

对象:

CREATE OR REPLACE TYPE WEEK_INVENTORY IS OBJECT
(ID INTEGER, DAY_1 INTEGER, DAY_2 INTEGER, DAY_3 INTEGER, DAY_4 INTEGER, DAY_5 INTEGER, DAY_6 INTEGER, DAY_7 INTEGER);
/

CREATE OR REPLACE TYPE WEEK_INVENTORIES IS TABLE OF WEEK_INVENTORY;
/

Type created.
Type created.

和功能。输入DATE是7天窗口的开始。该函数进行动态调整,在7天的窗口中每天汇总每个ID的库存。对于此示例,所有日期都将被截断(我不确定实际数据是否需要此日期)。

CREATE OR REPLACE FUNCTION SEVEN_DAYS_OF_INVENTORY(P_START_DATE IN DATE DEFAULT SYSDATE - 7) RETURN WEEK_INVENTORIES
IS
V_BUCKETS_CLAUSE CHARACTER VARYING(256);
V_WEEK_INVENTORIES WEEK_INVENTORIES := WEEK_INVENTORIES();
BEGIN
    SELECT LISTAGG('DATE '''||TO_CHAR(P_START_DATE + (LEVEL - 1),'YYYY-MM-DD')||''' AS DAY_'||LEVEL,',')
        WITHIN GROUP(ORDER BY NULL)
        INTO V_BUCKETS_CLAUSE
    FROM  DUAL CONNECT BY LEVEL <= 7;

    EXECUTE IMMEDIATE UTL_LMS.FORMAT_MESSAGE('SELECT WEEK_INVENTORY(ID, DAY_1, DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7) FROM
(SELECT ID, INVENTORY, TRUNC(DAY) AS TRUNC_DAY FROM TBL)
PIVOT (SUM(INVENTORY) FOR TRUNC_DAY IN (%s))
ORDER BY ID ASC',V_BUCKETS_CLAUSE) BULK COLLECT INTO V_WEEK_INVENTORIES;
RETURN V_WEEK_INVENTORIES;
END;
/

Function created.

然后对其进行测试:

默认(今天是2019年5月7日,因此从2019年4月30日开始):

SELECT * FROM TABLE(SEVEN_DAYS_OF_INVENTORY());

结果:

       ID    DAY_1    DAY_2    DAY_3    DAY_4    DAY_5    DAY_6    DAY_7
_________ ________ ________ ________ ________ ________ ________ ________
       12                          8
     1223                 1        5
     1234               467      493
   412345                          3        1

然后将其向前移动一天(2019年5月1日至2019年5月7日):

SELECT * FROM TABLE(SEVEN_DAYS_OF_INVENTORY(SYSDATE - 6));

结果:

       ID    DAY_1    DAY_2    DAY_3    DAY_4    DAY_5    DAY_6    DAY_7
_________ ________ ________ ________ ________ ________ ________ ________
       12                 8
     1223        1        5
     1234      467      493
   412345                 3        1

或两天(2019年5月2日至2019年5月8日):

SELECT * FROM TABLE(SEVEN_DAYS_OF_INVENTORY(DATE '2019-05-02'));

结果:

       ID    DAY_1    DAY_2    DAY_3    DAY_4    DAY_5    DAY_6    DAY_7
_________ ________ ________ ________ ________ ________ ________ ________
       12        8
     1223        5
     1234      493
   412345        3        1