2014-09-13 51 views
1

我有一个生成星期五和星期四的firebird程序。我用下面的查询生成数据列表:需要SQL Firebird数据透视表转换

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 

它会生成以下结果:

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 

有谁知道如何将数据转换成显示数据透视表如下:

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

日期是动态创建的,每次查询运行时都会有所不同,因此静态查询将无法正常工作。

回答

0

Derek,

在我的工作中,我们遇到了类似的情况。我们的代码正在从客户端执行,因此我们最终创建了一个返回SQL语句的存储过程,然后我们执行了返回的sql语句。

为了将完成你的任务,我创建了一个名为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 

一个助手存储过程我创建了以下使用EXECUTE BLOCK,但可以很容易地放置在另一个存储过程。

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; 

当您执行存储过程时,它将返回以下SQL,然后您可以执行该SQL。

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) 

我几件事情我想指出的.. 的是,我不能让列标题来完全按照你想要的。 此示例仅适用于星期四字段,您需要更改代码以处理星期五字段。 我假设你可能有相同的日期,促销和课程的倍数,所以我总结助手存储过程中的注册字段。我希望这有助于,