扩展枢轴

时间:2017-12-14 02:42:07

标签: sql-server pivot sql-server-2016-express

我有一个Documents表和一个Events表。

  • Documents表有ID和一堆其他与之无关的字段 这个问题。
  • 事件表包含DocID,EventType,EventDate和UserID。

文档可能包含以下任何EventTypes的零个或多个事件:

  • 0 =已创建
  • 1 =已修改
  • 2 =已提交
  • 3 =已批准
 DocID  | EventType | EventDate | UserID
-----------------------------------------------
    1   |    0      | 1-2-2017  |  123  
    1   |    1      | 1-3-2017  |  456
    1   |    1      | 1-4-2017  |  489
    1   |    2      | 1-5-2017  |  357
    2   |    0      | 1-6-2017  |  951
    2   |    1      | 1-7-2017  |  654
    2   |    2      | 1-8-2017  |  654
    2   |    3      | 1-9-2017  |  357

透过事件表很容易:

SELECT DocID, [0] AS CreatedDate, [1] AS ModifiedDate,
              [2] AS SubmittedDate, [3] AS ApprovedDate
FROM (SELECT DocID, EventType, EventDate FROM Events
WHERE DocID IS NOT NULL AND EventDate IS NOT NULL) AS DocEvents
PIVOT (MAX(EventDate) FOR EventType IN ([0], [1], [2], [3]))
AS DocEventsPivot

出于我的目的,需要给定类型的最新事件,因此MAX聚合:

DocID | CreatedDate | ModifiedDate | SubmittedDate | ApprovedDate
-----------------------------------------------------------------
  1   |   1-2-2017  |    1-4-2017  |    1-5-2017   |     NULL
  2   |   1-6-2017  |    1-7-2017  |    1-8-2017   |   1-9-2017

如何将UserID转换为CreatedBy,ModifiedBy,SubmittedBy和ApprovedBy以对应相应EventType的日期?

我不会提前知道UserID的可能值。

期望的输出:

DocID | CreatedDate | ModifiedDate | SubmittedDate | ApprovedDate | CreatedBy | ModifiedBy | SubmittedBy | ApprovedBy
---------------------------------------------------------------------------------------------------------------------
  1   |   1-2-2017  |    1-4-2017  |    1-5-2017   |     NULL     |    123    |    489     |     357     |    NULL
  2   |   1-6-2017  |    1-7-2017  |    1-8-2017   |   1-9-2017   |    951    |    654     |     654     |    657

2 个答案:

答案 0 :(得分:2)

而不是使用PIVOT,另一种解决方案是使用OUTER APPLY

CREATE TABLE #Documents (ID int)
CREATE TABLE #Events (DocID int, EventType int, EventDate date, UserID int)

INSERT INTO #Documents VALUES
(1),
(2)

INSERT INTO #Events VALUES
(1, 0, '1-2-2017', 123),  
(1, 1, '1-3-2017', 456),
(1, 1, '1-4-2017', 489),
(1, 2, '1-5-2017', 357),
(2, 0, '1-6-2017', 951),
(2, 1, '1-7-2017', 654),
(2, 2, '1-8-2017', 654),
(2, 3, '1-9-2017', 357)

SELECT
    DOC.ID AS 'DocID',
    CRT.EventDate AS 'CreatedDate',
    MFY.EventDate AS 'ModifiedDate',
    SUB.EventDate AS 'SubmittedDate',
    APR.EventDate AS 'ApprovedDate',
    CRT.UserID AS 'CreatedBy',
    MFY.UserID AS 'ModifiedBy',
    SUB.UserID AS 'SubmittedBy',
    APR.UserID AS 'ApprovedBy'
FROM 
    #Documents AS DOC
    OUTER APPLY (SELECT TOP 1 EventDate, UserID FROM #Events WHERE DocID = DOC.ID AND EventType = 0 ORDER BY EventDate DESC) AS CRT
    OUTER APPLY (SELECT TOP 1 EventDate, UserID FROM #Events WHERE DocID = DOC.ID AND EventType = 1 ORDER BY EventDate DESC) AS MFY
    OUTER APPLY (SELECT TOP 1 EventDate, UserID FROM #Events WHERE DocID = DOC.ID AND EventType = 2 ORDER BY EventDate DESC) AS SUB
    OUTER APPLY (SELECT TOP 1 EventDate, UserID FROM #Events WHERE DocID = DOC.ID AND EventType = 3 ORDER BY EventDate DESC) AS APR

DROP TABLE #Documents
DROP TABLE #Events

答案 1 :(得分:1)

尝试以下

6

或者您可以使用for (i = 0; i < data.length; i++) { profileId = data[i][0]; clientCms = data[i][1]; goalList = data[i][3]; var goal1 = 'ga:goal' + goalList[0].toString() + 'Completions' var goal2 = 'ga:goal' + goalList[1].toString() + 'Completions' var goal3 = 'ga:goal' + goalList[2].toString() + 'Completions' var goal4 = 'ga:goal' + goalList[3].toString() + 'Completions' 代替CREATE TABLE #Events (DocID int, EventType int, EventDate date, UserID int) INSERT INTO #Events VALUES (1, 0, '1-2-2017', 123), (1, 1, '1-3-2017', 456), (1, 1, '1-4-2017', 489), (1, 2, '1-5-2017', 357), (1, 2, '1-4-2017', 666), (2, 0, '1-6-2017', 951), (2, 1, '1-7-2017', 654), (2, 2, '1-8-2017', 654), (2, 3, '1-9-2017', 357) SELECT DocID, MAX(CASE WHEN EventType=0 THEN EventDate END) [CreatedDate], MAX(CASE WHEN EventType=1 THEN EventDate END) [ModifiedDate], MAX(CASE WHEN EventType=2 THEN EventDate END) [SubmittedDate], MAX(CASE WHEN EventType=3 THEN EventDate END) [ApprovedDate], MAX(CASE WHEN EventType=0 THEN LastUserID END) [CreatedBy], MAX(CASE WHEN EventType=1 THEN LastUserID END) [ModifiedBy], MAX(CASE WHEN EventType=2 THEN LastUserID END) [SubmittedBy], MAX(CASE WHEN EventType=3 THEN LastUserID END) [ApprovedBy] FROM ( SELECT DocID, EventDate, EventType, LAST_VALUE(UserID)OVER( PARTITION BY DocID,EventType ORDER BY EventDate ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) LastUserID FROM #Events ) q GROUP BY DocID DROP TABLE #Events 。我更喜欢使用IFF,因为它不是阻止CASE

CASE
相关问题