2016-11-20 47 views
2

是否有可能採取以下面的方式構成的表:那最終進入像這樣的表具有獨立where子句的多個列 - SQL Pivot?

ID Month  Info1 Info2 
1  1   A  B 
1  2   C  D 
1  3   E  F 
2  3   G  H 
2  4   I  J 

ID JanInfo1 JanInfo2 FebInfo1 FebInfo2 MarInfo1 MarInfo2 AprInfo1 AprInfo2 
1  A  B  C  D  E  F  NULL NULL 
2  NULL  NULL NULL  NULL  G  H   I  J 

我已經研究過使用基點和couldn」讓他們工作。

我目前每個月都使用CROSS APPLY表值函數。

有沒有更好的方法來做到這一點?

編輯:增加現有的查詢 - 試圖簡化顯示:

-- Get the unique IDs 
DECLARE @PersonIds TABLE 
(
    UploadID UNIQUEIDENTIFIER, 
    PersonId VARCHAR(200), 
    RecordYear INT 
) 
INSERT INTO @PersonIds 
    SELECT DISTINCT UploadID, PersonId, RecordYear 
    FROM [VERTICALTABLE] 
    WHERE UploadID = @PTPUploadID 
      AND RecordYear = @RecordYear 
     GROUP BY UploadID, PersonId, RecordYear 

-- Flatten via functions 
INSERT INTO [FLATTABLE](PersonID, JanuaryCoverage, FebruaryCoverage, MarchCoverage, AprilCoverage, MayCoverage, JuneCoverage, 
     JulyCoverage, AugustCoverage, SeptemberCoverage, OctoberCoverage, NovemberCoverage, DecemberCoverage) 

    SELECT PID.PersonID, M1.Covered, M2.Covered, M3.Covered, M4.Covered, M5.Covered, M6.Covered, 
     M7.Covered, M8.Covered, M9.Covered, M10.Covered, M11.Covered, M12.Covered 
    FROM @PersonIds AS PID 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 1, PID.PersonId) AS M1 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 2, PID.PersonId) AS M2 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 3, PID.PersonId) AS M3 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 4, PID.PersonId) AS M4 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 5, PID.PersonId) AS M5 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 6, PID.PersonId) AS M6 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 7, PID.PersonId) AS M7 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 8, PID.PersonId) AS M8 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 9, PID.PersonId) AS M9 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 10, PID.PersonId) AS M10 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 11, PID.PersonId) AS M11 
    OUTER APPLY GetMonthInfpo(@PTPUploadID, @RecordYear, 12, PID.PersonId) AS M12 
    WHERE UploadID = @PTPUploadID 
     AND RecordYear = @RecordYear 

的功能看起來像

ALTER FUNCTION GetMonthInfpo( 
( 
    @UploadID UNIQUEIDENTIFIER, 
    @Year INT, 
    @Month INT, 
    @PersonID VARCHAR(200) 
) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT COUNT(*) AS 'Covered' 
    FROM [VERTICALTABLE] 
    WHERE UploadID = @UploadID 
     AND RecordYear = @Year 
     AND RecordMonth = @Month 
     AND PersonId = @PersonID 
) 
+0

您可以顯示爲您當前的查詢嗎? –

+0

已添加 - 試圖簡化 –

+0

在這種情況下應用功能不是好主意。設置統計信息並與其他查詢進行比較 - 對於透視使用PIVOT子句。 – Deadsheep39

回答

2

您不需要多個子查詢。答案很簡單 - 使用集合論。從你的第一個表ID /月/信息1 /信息2做ID /月+(1 + 2)/方便工會信息 - 例如:

select ID, cast(Month as varchar(10)) + cast('_1' as varchar(10)) ComposedMonth, Info1 Info 
from tbl 
union all 
select ID, cast(Month as varchar(10)) + cast('_2' as varchar(10)), Info2 
from tbl 

然後在此數據集使用(呈現爲視圖或臨時表) pivot條款。

select * 
from vw_tbl t 
pivot (max(Info) for ComposedMonth in ([1_1], [1_2]...)) p 
-- or if you will cast month to text 
-- pivot (max(Info) for ComposedMonth in ([Jan_1], [Jan_2]...)) p 

組成字符串是輕鬆旋轉的關鍵。

+0

這真是太棒了,謝謝!我無法確定我的東西的工作方式,但速度提高了10倍,並且減少了抖動。 –

1

有了更新的信息

SELECT 
    t.PersonID, 
    JanuaryCoverage  = SUM(CASE WHEN t.RecordMonth = 1 THEN Info1 ELSE 0 END), 
    FebruaryCoverage = SUM(CASE WHEN t.RecordMonth = 2 THEN Info1 ELSE 0 END), 
    MarchCoverage  = SUM(CASE WHEN t.RecordMonth = 3 THEN Info1 ELSE 0 END), 
    AprilCoverage  = SUM(CASE WHEN t.RecordMonth = 4 THEN Info1 ELSE 0 END), 
    MayCoverage   = SUM(CASE WHEN t.RecordMonth = 5 THEN Info1 ELSE 0 END), 
    JuneCoverage  = SUM(CASE WHEN t.RecordMonth = 6 THEN Info1 ELSE 0 END), 
    JulyCoverage  = SUM(CASE WHEN t.RecordMonth = 7 THEN Info1 ELSE 0 END), 
    AugustCoverage  = SUM(CASE WHEN t.RecordMonth = 8 THEN Info1 ELSE 0 END), 
    SeptemberCoverage = SUM(CASE WHEN t.RecordMonth = 9 THEN Info1 ELSE 0 END), 
    OctoberCoverage  = SUM(CASE WHEN t.RecordMonth = 10 THEN Info1 ELSE 0 END), 
    NovemberCoverage = SUM(CASE WHEN t.RecordMonth = 11 THEN Info1 ELSE 0 END), 
    DecemberCoverage = SUM(CASE WHEN t.RecordMonth = 12 THEN Info2 ELSE 0 END) 
FROM [VERTICALTABLE] t 
WHERE 
    t.UploadID = @UploadID 
    AND RecordYear = @Year 
GROUP BY t.PersonId; 

使用條件聚合:

SELECT 
    t.ID, 
    JanInfo1 = MAX(CASE WHEN t.[Month] = 1 THEN Info1 END), 
    JanInfo2 = MAX(CASE WHEN t.[Month] = 1 THEN Info2 END), 
    FebInfo1 = MAX(CASE WHEN t.[Month] = 2 THEN Info1 END), 
    FebInfo2 = MAX(CASE WHEN t.[Month] = 2 THEN Info2 END), 
    MarInfo1 = MAX(CASE WHEN t.[Month] = 3 THEN Info1 END), 
    MarInfo2 = MAX(CASE WHEN t.[Month] = 3 THEN Info2 END), 
    AprInfo1 = MAX(CASE WHEN t.[Month] = 4 THEN Info1 END), 
    AprInfo2 = MAX(CASE WHEN t.[Month] = 4 THEN Info2 END), 
    MayInfo1 = MAX(CASE WHEN t.[Month] = 5 THEN Info1 END), 
    MayInfo2 = MAX(CASE WHEN t.[Month] = 5 THEN Info2 END), 
    JunInfo1 = MAX(CASE WHEN t.[Month] = 6 THEN Info1 END), 
    JunInfo2 = MAX(CASE WHEN t.[Month] = 6 THEN Info2 END), 
    JulInfo1 = MAX(CASE WHEN t.[Month] = 7 THEN Info1 END), 
    JulInfo2 = MAX(CASE WHEN t.[Month] = 7 THEN Info2 END), 
    AugInfo1 = MAX(CASE WHEN t.[Month] = 8 THEN Info1 END), 
    AugInfo2 = MAX(CASE WHEN t.[Month] = 8 THEN Info2 END), 
    SepInfo1 = MAX(CASE WHEN t.[Month] = 9 THEN Info1 END), 
    SepInfo2 = MAX(CASE WHEN t.[Month] = 9 THEN Info2 END), 
    OctInfo1 = MAX(CASE WHEN t.[Month] = 10 THEN Info1 END), 
    OctInfo2 = MAX(CASE WHEN t.[Month] = 10 THEN Info2 END), 
    NovInfo1 = MAX(CASE WHEN t.[Month] = 11 THEN Info1 END), 
    NovInfo2 = MAX(CASE WHEN t.[Month] = 11 THEN Info2 END), 
    DecInfo1 = MAX(CASE WHEN t.[Month] = 12 THEN Info1 END), 
    DecInfo2 = MAX(CASE WHEN t.[Month] = 12 THEN Info2 END) 
FROM Tbl t 
GROUP BY t.ID; 
+0

謝謝!我玩過它,但與目前相比,它運行時間明顯更長(平滑1M記錄左右) - 我會四處遊覽,看看它是否可以優化,因爲我喜歡它的清潔程度。 –