Поскольку в возвращении нет необходимости указывать конкретные имена столбцов, один из подходов к этому типу - PIVOT
.
PIVOT
может быть строгим при наличии статических сегментов, поэтому пример здесьиспользует динамический sql для перемещения 7-дневного окна.
У такого подхода есть некоторые реальные недостатки - динамический sql, скомпилированные объекты, грязный код и т. д., поэтому я не решаюсь на самом деле рекомендовать такой подход, но с использованием динамическогоsql позволяет предоставлять статические сегменты для PIVOT
.
Ниже приведен пример с использованием предоставленной вами таблицы.
В этом примере будет суммироваться весь инвентарь за ID
за каждый день за семидневный период, начинающийся с указанной даты.(По умолчанию за семь дней до сегодняшнего дня (исключая сегодняшний день)).
Чтобы разрешить вызов этого из 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
является началом семидневного окна.Функция выполняет динамический разворот, суммируя инвентарь для каждого 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.
Затем проверьте его:
По умолчанию (сегодня 7 мая 2019 г., поэтому он начинается с 30 апреля 2019 г.):
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
Затем переместите его вперед на один день (1 мая 2019 г. - 7 мая 2019 г.):
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
Или два дня (2 мая, 2019 - 8 мая 2019):
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