Oracle SQL Dynamic PIVOT Текущий месяц, последние 6 месяцев и всего - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть простой запрос, который возвращает мои базовые данные:

SELECT b.MRID, r.GID, b.VDATE
FROM BAC b
LEFT JOIN BAR r ON b.MRID = r.RID

, который выводит:

MRID           GID  VDATE
John Smith     com  15-Oct-18
John Smith     com  NULL
Joe Bloggs     ad   02-Jun-18
Joe Bloggs     ad   14-Jul-18
Homer Simpson  bil  17-Oct-18
Homer Simpson  bil  NULL
Rick Grimes    zee  12-Nov-18
Rick Grimes    zee  NULL

То, что я хочу вывести, - это динамический PIVOT:

MRID           GID  Current Month   Oct-18  Sep-18  Aug-18  Jul-18  Jun-18  May-18  Total
John Smith     com  0               1      0        0       0       0       0       1
Joe Bloggs     ad   0               0      0        0       1       1       0       2
Homer Simpson  bil  0               1      0        0       0       0       0       1
Rick Grimes    zee  1               0      0        0       0       0       0       1

Я хочу, чтобы это динамически изменялось по мере того, как месяцы переходят на текущий месяц и общее количество.

1 Ответ

0 голосов
/ 28 ноября 2018

Изменение имени столбца динамически будет затруднено.Есть несколько решений, но ни одно из них не является действительно тем, что вам нужно

1) Выполнение «сводного XML» с указанием ЛЮБОГО в списке значений, которые вы хотите включить.Но он даст вам результат в виде XML, который ... не идеален

2) Выполнение функции PIPELINED, принимающей курсор, который создаст для вас опорный пункт.Но это требует создания типов и хранимых процедур

Если вы согласны изменить имена столбцов на что-то общее, например MONTH-1 ... вы можете легко сделать это, как показано ниже:

CREATE TABLE BAC ( MRID VARCHAR2(30), VDATE DATE );
CREATE TABLE BAR ( RID VARCHAR2(30), GID VARCHAR2(3));

INSERT INTO BAC VALUES ( 'John Smith',TO_DATE('15-Oct-18','DD-MON-YY'));
INSERT INTO BAC VALUES ( 'John Smith',null);
INSERT INTO BAC VALUES ( 'Joe Bloggs',TO_DATE('02-Jun-18','DD-MON-YY'));
INSERT INTO BAC VALUES ( 'Joe Bloggs',TO_DATE('14-Jul-18','DD-MON-YY'));
INSERT INTO BAC VALUES ( 'Homer Simpson',TO_DATE('17-Oct-18','DD-MON-YY'));
INSERT INTO BAC VALUES ( 'Homer Simpson',null);
INSERT INTO BAC VALUES ( 'Rick Grimes',TO_DATE('12-Nov-18','DD-MON-YY'));
INSERT INTO BAC VALUES ( 'Rick Grimes',null);

INSERT INTO BAR VALUES ( 'John Smith','com');
INSERT INTO BAR VALUES ( 'Joe Bloggs','ad');
INSERT INTO BAR VALUES ( 'Homer Simpson','bil');
INSERT INTO BAR VALUES ( 'Rick Grimes','zee');

WITH MONTHS AS 
(
    SELECT ADD_MONTHS(TRUNC(SYSDATE,'MONTH'),-LEVEL+1) AS MONTH, DECODE(LEVEL,1,'CURRENT_MONTH','MONTH_MINUS_'||(LEVEL-1)) AS MONTH_NAME FROM DUAL CONNECT BY LEVEL <=7
)
SELECT 
        MRID, 
        GID,
        NVL(CURRENT_MONTH,0) AS CURRENT_MONTH,
        NVL(MONTH_MINUS_1,0) AS MONTH_MINUS_1,
        NVL(MONTH_MINUS_2,0) AS MONTH_MINUS_2,
        NVL(MONTH_MINUS_3,0) AS MONTH_MINUS_3,
        NVL(MONTH_MINUS_4,0) AS MONTH_MINUS_4,
        NVL(MONTH_MINUS_5,0) AS MONTH_MINUS_5,
        NVL(MONTH_MINUS_6,0) AS MONTH_MINUS_6,
        TOTAL 
FROM (
    SELECT 
        DISTINCT B.MRID, R.GID, MONTH_NAME, 
        COUNT(*) OVER (PARTITION BY B.MRID, R.GID, TRUNC(VDATE,'MONTH') ORDER BY VDATE ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS CNT, 
        COUNT(*) OVER (PARTITION BY B.MRID, R.GID ORDER BY VDATE ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS TOTAL
    FROM MONTHS M
    JOIN BAC B ON M.MONTH=TRUNC(B.VDATE,'MONTH')
    LEFT JOIN BAR R ON b.MRID = r.RID 
) PIVOT 
( SUM(CNT) 
    FOR MONTH_NAME IN 
        ('CURRENT_MONTH' AS CURRENT_MONTH ,
        'MONTH_MINUS_1' AS MONTH_MINUS_1,
        'MONTH_MINUS_2' AS MONTH_MINUS_2,
        'MONTH_MINUS_3' AS MONTH_MINUS_3,
        'MONTH_MINUS_4' AS MONTH_MINUS_4,
        'MONTH_MINUS_5' AS MONTH_MINUS_5,
        'MONTH_MINUS_6' AS MONTH_MINUS_6)
);

MRID                           GID CURRENT_MONTH MONTH_MINUS_1 MONTH_MINUS_2 MONTH_MINUS_3 MONTH_MINUS_4 MONTH_MINUS_5 MONTH_MINUS_6      TOTAL
------------------------------ --- ------------- ------------- ------------- ------------- ------------- ------------- ------------- ----------
John Smith                     com             0             1             0             0             0             0             0          1
Rick Grimes                    zee             1             0             0             0             0             0             0          1
Homer Simpson                  bil             0             1             0             0             0             0             0          1
Joe Bloggs                     ad              0             0             0             0             1             1             0          2
...