SQL Firebird Pivot table conversion required

别等时光非礼了梦想. 提交于 2021-01-28 13:30:07

问题


I have a procedure that generated Friday and Thursday date in firebird. I use the following query to generate a list of data:

    select w_start as "Friday", w_end as "Thursday",
(select count(*) from course C 
                         inner join enrolment E on E.cod_course=C.id
                         where E.date_enrolled between w_start and w_end
                                   and C_TYPE = 'PU' and CONFIRMED='C'  
                                  and (C.name like :PublicCourseOption1  or C.name like :PublicCourseOption2 or C.name like :PublicCourseOption3  or C.name like :PublicCourseOption4 
                                         or C.VERSION like :CourseVersion1 or C.version like :CourseVersion2  or C.version like :CourseVersion3 )
) as "Enrolments",
(select list(distinct promotype, ', ') from programmers where datesent between w_start and w_end) as "Promos", 
(select list(distinct course, ', ') from programmers where datesent between w_start and w_end) as "Courses"
from get_weeks(:dtFromDate, :dtToDate) wks
order by w_start

It generates the following result:

Friday      Thursday    Enrolments  Promos                Courses
04/01/2013  10/01/2013  5           FAX                   WHS
11/01/2013  17/01/2013  11          EMAIL                 WHS
18/01/2013  24/01/2013  6           FAX                   WHS
25/01/2013  31/01/2013  12          EMAIL, FAX            RTW, YSM103
01/02/2013  07/02/2013  17          EMAIL, FAX, Wcover    REF-CIT, WHS Toll, WorkCover
08/02/2013  14/02/2013  19          FAX                   HSR HUR- INFO
15/02/2013  21/02/2013  12          FAX                   MC
22/02/2013  28/02/2013  19          EMAIL, FAX            ARTW, DYS25, MC
01/03/2013  07/03/2013  22          COMCARE, FAX, Wcover  COMCARE, COMM, WorkCover
08/03/2013  14/03/2013  13          FAX                   HSR
15/03/2013  21/03/2013  12
22/03/2013  28/03/2013  16          FAX                   HSR

Does anyone know how to convert the data into a pivot table showing as follows:

Promos- Course - 10/01/2013 (Thursday Date)    - 17/01/2013 (Thursday Date)
FAX   -  WHS   - 15 enrolments                 - 25 enrolments
EMAIL -  MC    - 14 Enrolments                 - 36 enrolments

The dates are dynamically created and can vary every time the query is run, so static query wont work for what I need.


回答1:


Derek,

In my line of work we ran into a similar situation. Our code was being executed from a Client so we ended up doing was creating a Stored Procedure that returned the SQL Statement, then we executed the sql Statement returned.

In order to the accomplish you task, i created a Helper Stored Procedure called X_GET_ENROLLMENTS_FOR_DATE

CREATE OR ALTER PROCEDURE X_GET_ENROLLMENTS_FOR_DATE (
    PROMOS VARCHAR(100),
    COURSES VARCHAR(100),
    DATE_STRING VARCHAR(30))
RETURNS (
    ENROLLMENTS INTEGER)
AS
BEGIN

  SELECT SUM(ENROLLMENTS)
  FROM TABLE_X
  WHERE TABLE_X.PROMOS = :PROMOS
        AND TABLE_X.COURSES = :COURSES
        AND TABLE_X.THURSDAY = :DATE_STRING
  INTO ENROLLMENTS;

  SUSPEND;
END

And I created the following using EXECUTE BLOCK, but could easily be placed in another Stored Procedure.

EXECUTE BLOCK
RETURNS (
    SQL VARCHAR(3000))
AS
DECLARE VARIABLE SELECT_SQL VARCHAR(2000);
DECLARE VARIABLE WHERE_SQL VARCHAR(2000);
DECLARE VARIABLE PROMOS VARCHAR(30);
DECLARE VARIABLE COURSES VARCHAR(30);
DECLARE VARIABLE THURSDAY VARCHAR(30);
DECLARE VARIABLE ENROLLMENTS INTEGER;
DECLARE VARIABLE FIELD_ID INTEGER; --DECLARE VARIABLE S varchar(1000)
DECLARE VARIABLE FIELD_COUNT INTEGER;
BEGIN
  SELECT_SQL = 'SELECT distinct promos, courses ,' || ASCII_CHAR(13);
  WHERE_SQL = 'FROM table_x' || ASCII_CHAR(13);

  FIELD_ID = 0;

  SELECT COUNT(DISTINCT THURSDAY)
  FROM TABLE_X
  INTO :FIELD_COUNT;

  FOR
  SELECT DISTINCT THURSDAY
  FROM TABLE_X
  INTO :THURSDAY
  DO
  BEGIN
    FIELD_ID = :FIELD_ID + 1;
    IF (:FIELD_ID = :FIELD_COUNT) THEN
      SELECT_SQL = :SELECT_SQL || 'T' || :FIELD_ID || '.Enrollments ' || 'Thu_' || REPLACE(:THURSDAY, '/', '_') || ASCII_CHAR(13);
    ELSE
      SELECT_SQL = :SELECT_SQL || 'T' || :FIELD_ID || '.Enrollments ' || 'Thu_' || REPLACE(:THURSDAY, '/', '_') || ',' || ASCII_CHAR(13);

    WHERE_SQL = :WHERE_SQL || 'LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, ''' || :THURSDAY || ''') T' || :FIELD_ID || ' on (1 = 1)' || ASCII_CHAR(13);
    --    WHERE_SQL = :WHERE_SQL || 'INNER JOIN ( Select Sum(Enrollments) Enrollments from table_x where promos = ''' || :PROMOS || ''' and Courses = ''' || :COURSES || ''' and thursday = ''' || :THURSDAY || ''') T' || :FIELD_ID || ' on (1 = 1)' || ASCII_CHAR(13);

  END
  SQL = :SELECT_SQL || :WHERE_SQL;
  SUSPEND;
END; 

When you execute the Stored procedure it will return back the following SQL, which you can then execute.

SELECT distinct promos, courses ,
T1.Enrollments Thu_07_02_2013,
T2.Enrollments Thu_07_03_2013,
T3.Enrollments Thu_10_01_2013,
T4.Enrollments Thu_14_02_2013,
T5.Enrollments Thu_14_03_2013,
T6.Enrollments Thu_17_01_2013,
T7.Enrollments Thu_21_02_2013,
T8.Enrollments Thu_21_03_2013,
T9.Enrollments Thu_24_01_2013,
T10.Enrollments Thu_28_02_2013,
T11.Enrollments Thu_28_03_2013,
T12.Enrollments Thu_31_01_2013
FROM table_x
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '07/02/2013') T1 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '07/03/2013') T2 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '10/01/2013') T3 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '14/02/2013') T4 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '14/03/2013') T5 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '17/01/2013') T6 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '21/02/2013') T7 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '21/03/2013') T8 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '24/01/2013') T9 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '28/02/2013') T10 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '28/03/2013') T11 on (1 = 1)
LEFT OUTER JOIN X_GET_ENROLLMENTS_FOR_DATE ( table_x.PROMOS,table_x.COURSES, '31/01/2013') T12 on (1 = 1)

I few things i want to point out.. is that i couldn't get the column headers to come exactly as you wanted. This example is only works on Thursday field, you will need to make changes to code to handle the Friday field. I am assuming that you might have multiples of same date, promo and courses so i am summing the enrollments fields in the helper stored procedure.

I hope this helps,



来源:https://stackoverflow.com/questions/25822132/sql-firebird-pivot-table-conversion-required

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!