我正在尝试编写一个查询,以查询过去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
答案 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