【问题标题】:PIVOT with dynamic columns and JOINS 5+ tables具有动态列和 JOINS 5+ 表的 PIVOT
【发布时间】:2019-08-26 05:31:01
【问题描述】:

这是我之前发布的问题的扩展,可以在这里找到:Previous Question

现在我还有 2 个表也连接到 ProfileFan 跟踪粉丝的活动 (ProfileFan)。

Table Fan
-----------------------
| FanId | Name | Info |
-----------------------
| 17111 | Fan1 | Info1|
-----------------------  
| 17112 | Fan2 | Info2|
-----------------------

    Table ProfileFan m:1 Fan FanId(FK)
    -----------------------------------
    | Id | LinkedInProfileId | FanId |
    -----------------------------------
    | 1111    | 1          | 17111   |
    ---------------------------------
    | 1112    | 2          | 17111   |
    ----------------------------------
    | 1113    | 1          | 17112   |
    ----------------------------------
    | 1114    | 2          | 17112   |
    ----------------------------------

    Table LinkedInProfile
    --------------------------
    | Id   | Name    | Client |
    --------------------------
    | 1    | Linked1 | Client1|
    --------------------------
    | 2    | Linked2 | Client1|
    --------------------------

    Table FanActivity m:1 ProfileFan via ProfileFanId (FK)
    ------------------------------------------------
    | Id   | Created    | ProfileFanId | ActivityId |
    -------------------------------------------------
    | 1    | 2019-01-05 |    17111     |     1      |
    -------------------------------------------------
    | 2    | 2019-01-05 |    17111     |     2      |
    -------------------------------------------------
    | 3    | 2019-01-05 |    17112     |     3     |
    -------------------------------------------------
    | 4    | 2019-01-05 |    17112     |     4      |
    -------------------------------------------------

    Table Activity Id(PK) 
    --------------------
    | Id   | Name        | 
    ---------------------
    | 1    | ConAccepted |
    ---------------------
    | 2    | Message     |
    ---------------------
    | 3    | LikesContent |  
    ----------------------
    | 4    | JoinsGroup  |        
    ----------------------

    Table DeliveryActions m:1 ProfileFan via ProfileFanId (FK)
    ------------------------------------------------------
    | Id   | LoggedAt   | ProfileFanId | DeliveryActionId |
    -------------------------------------------------------
    | 1    | 2019-01-05 |    17111     |     1            |
    ------------------------------------------------------
    | 2    | 2019-01-05 |    17111     |     2            |
    ------------------------------------------------------
    | 3    | 2019-01-05 |    17112     |     3            |
    ------------------------------------------------------
    | 4    | 2019-01-05 |    17112     |     4            |
    ------------------------------------------------------

    Table DeliveryAction Id(PK) 
    ------------------------
    | Id   | Name           | 
    ------------------------
    | 1    | M1             |
    ------------------------
    | 2    | M2             |
    ------------------------
    | 3    | M3             |  
    ------------------------
    | 4    | M4             |        
    ------------------------

查询的输出应如下所示。

    -------------------------------------------------------------------------------------------------------------------------------------------------------
    | Name | Info  | LinkedInProfile1| LinkedInProfile2 | Client |ConAccepted | Message | LikesContent | JoinsGroup |     M1     |    M2     |      M3     |     M4     |
    ---------------------------------------------------------------------------------------------------------------------------------------------------
    | Name1 | Info1|  Linked1(1111)  | Linked2(1112)   | Client1 | 2019-01-05 | 2019-01-06 | 2019-01-07 | 2019-01-08 | 2019-01-09 | 2019-01-05 |2019-01-06 | 2019-01-07 |
    ---------------------------------------------------------------------------------------------------------------------------------------------------
    | Name2 | Info2|  Linked1(1113)  | Linked2(1114)    | Client1 |2019-01-05 | 2019-01-06 | 2019-01-07 | 2019-01-08 | 2019-01-09 | 2019-01-05 |2019-01-05 | 2019-01-0 |
    ---------------------------------------------------------------------------------------------------------------------------------------------------

我需要在单行中插入来自一个风扇的查询数据,而不是为给我连接的每一行插入多个数据。 到目前为止,正如stackoverflow用户所建议的那样,我已经通过使用PIVOT和动态查询来解决仅针对LinkedInProfile的解决方案。

我还在这里创建了一个模拟https://rextester.com/live/NYYK67222

我需要与 FanActivities 和 DeliveryActions 表进行适当的联接 在到目前为止的联接之上,并将数据放在每个 FAN 的一行中!

所以 1 个 FAN 在 2 个 LinkedInProfiles 下 -> 这会创建 2 个 ProfileFansId。所有 profileFans 都有很多 FanActivity 和很多 DeliveryAction。

我知道我需要在这里使用 PIVOT 和动态列。但这对我来说是全新的。

【问题讨论】:

  • 你走了多远?您是否有一些 SQL 可以正确连接数据但没有正确输出?
  • SELECT CONCAT(lip.Name,'(',pf.Id,')') AS val, f.Name as 'Name', f.Info as 'Info', CONCAT('LinkedInProfile',pf.ProfileId) as LipId FROM Fan f LEFT JOIN ProfileFan pf ON f.FanId = pf.FanId LEFT JOIN LinkedInProfile lip ON pf.ProfileId = lip.Id 这是我目前为止的情况
  • 在您的示例数据 (Rexter) 中没有为 FAN2 记录的粉丝活动和交付活动,但它们的值出现在您想要的输出中。怎么样??

标签: sql sql-server pivot outer-join dynamic-columns


【解决方案1】:

由于您想要的结果与您在 rexter 上的示例数据不同,我只修改了 FanActivities 和 DeliveryActions 表中的一些数据。

CREATE TABLE #Fan (FanId INT, Name VARCHAR(100), Info VARCHAR(100));

INSERT INTO #Fan
VALUES (17111, 'Fan1', 'Info1'), (17112, 'Fan2', 'Info2');

CREATE TABLE #LinkedInProfile (Id INT, Name VARCHAR(100), Client VARCHAR(100));

INSERT INTO #LinkedInProfile
VALUES (1, 'Linked1', 'Client1'), (2, 'Linked2', 'Client1');

CREATE TABLE #ProfileFan (Id INT, ProfileId INT, FanId INT);

INSERT INTO #ProfileFan
VALUES (1111, 1, 17111), (1112, 2, 17111), (1113, 1, 17112), (1114, 2, 17112);

CREATE TABLE #Activities (Id INT, Name VARCHAR(100));

INSERT INTO #Activities
VALUES (1, 'ConAccepted'), (2, 'Message'), (3, 'LikesContent'), (4, 'JoinsGroup');

CREATE TABLE #FanActivities (Id INT, Created VARCHAR(100), ProfileFanId INT
                           , ActivityId INT);

INSERT INTO #FanActivities
VALUES 
  (1, '2019-01-05', 1111, 1), (1, '2019-01-05', 1111, 2)
, (1, '2019-01-05', 1112, 3), (1, '2019-01-05', 1111, 4)
, (1, '2019-01-05', 1113, 1), (1, '2019-01-05', 1113, 2)
, (1, '2019-01-05', 1114, 3), (1, '2019-01-05', 1113, 4);

CREATE TABLE #DeliveryAction (Id INT, Name VARCHAR(100));

INSERT INTO #DeliveryAction
VALUES (1, 'M1'), (2, 'M2'), (3, 'M3'), (4, 'M4');

CREATE TABLE #DeliveryActions (Id INT, Created VARCHAR(100), ProfileFanId INT
                            , ActivityId INT);

INSERT INTO #DeliveryActions
VALUES 
  (1, '2019-01-05', 1111, 1), (1, '2019-01-05', 1111, 2)
, (1, '2019-01-05', 1112, 3), (1, '2019-01-05', 1111, 4)
, (1, '2019-01-05', 1113, 1), (1, '2019-01-05', 1113, 2)
, (1, '2019-01-05', 1114, 3), (1, '2019-01-05', 1113, 4);

您的查询将是

;WITH CTE AS(
SELECT F.FanId,F.Name AS FANNAME,F.Info 
,CONCAT(lip.Name,'(',pf.Id,')') AS LINKEDPROFILE
,CONCAT('#LinkedInProfile',pf.ProfileId) as LipId 
, LIP.Client
,FACT.Name AS FANACTIVITY, FA.Created FANACTIVITYDATE
,DA.Name AS DELVACTIVITY, DAS.Created DELVACTIVITYDATE
FROM #Fan F
LEFT JOIN #ProfileFan pf ON f.FanId = pf.FanId
LEFT JOIN #LinkedInProfile lip ON pf.ProfileId = lip.Id
LEFT JOIN #FanActivities FA ON PF.Id = FA.ProfileFanId
LEFT JOIN #ActivitieS FACT ON FACT.Id = FA.ActivityId
LEFT JOIN #DeliveryActions DAS ON PF.Id = DAS.ProfileFanId
LEFT JOIN #DeliveryAction DA ON DAS.ActivityId = DA.ID
)
SELECT FANNAME, Info, Client
,[#LinkedInProfile1],[#LinkedInProfile2]
,[ConAccepted],[Message],[LikesContent],[JoinsGroup]
,[M1],[M2],[M3],[M4] FROM (
SELECT  FANNAME, Info, Client,KEYS,VALUE
FROM CTE
CROSS APPLY (
    VALUES (LipId, LINKEDPROFILE)
    , (FANACTIVITY,FANACTIVITYDATE)
    ,(DELVACTIVITY,DELVACTIVITYDATE)
    )AS TAB(KEYS,VALUE)
)AS A
PIVOT
(
    MAX(VALUE) FOR KEYS IN ([#LinkedInProfile1],[#LinkedInProfile2]
    ,[ConAccepted],[Message],[LikesContent],[JoinsGroup]
    ,[M1],[M2],[M3],[M4])
)PV

我得到的结果

+---------+-------+---------+-------------------+-------------------+-------------+------------+--------------+------------+------------+------------+------------+------------+
| FANNAME | Info  | Client  | #LinkedInProfile1 | #LinkedInProfile2 | ConAccepted |  Message   | LikesContent | JoinsGroup |     M1     |     M2     |     M3     |     M4     |
+---------+-------+---------+-------------------+-------------------+-------------+------------+--------------+------------+------------+------------+------------+------------+
| Fan1    | Info1 | Client1 | Linked1(1111)     | Linked2(1112)     | 2019-01-05  | 2019-01-05 | 2019-01-05   | 2019-01-05 | 2019-01-05 | 2019-01-05 | 2019-01-05 | 2019-01-05 |
| Fan2    | Info2 | Client1 | Linked1(1113)     | Linked2(1114)     | 2019-01-05  | 2019-01-05 | 2019-01-05   | 2019-01-05 | 2019-01-05 | 2019-01-05 | 2019-01-05 | 2019-01-05 |
+---------+-------+---------+-------------------+-------------------+-------------+------------+--------------+------------+------------+------------+------------+------------+

【讨论】:

    【解决方案2】:

    帖子中的示例代码与您的 rextester 示例之间存在一些差异(例如,您的帖子中的 DeliveryActions.ProfileFanId 似乎引用了 Fan.FanId,但在 rextester 示例中它引用了 ProfileFan.Id)。我的答案是基于您的 rextester 样本。

    我个人的偏好是,如果不需要,就不要进行多个枢轴,而是使用交叉表查询……这对我来说更容易查看和理解,而不是多层枢轴。

    您可以在 rextester here 中看到这一点。

    SELECT 
        f.Name
        ,f.Info
        ,LinkedInProfile1 = MAX(CASE WHEN pf.ProfileId  = 1 THEN CONCAT(lip.Name,'(',pf.Id,')') END)
        ,LinkedInProfile2 = MAX(CASE WHEN pf.ProfileId  = 2 THEN CONCAT(lip.Name,'(',pf.Id,')') END)
        ,lip.Client
        ,ConAccepted = MAX(CASE WHEN a.Name = 'ConAccepted' THEN fa.Created END)
        ,Message = MAX(CASE WHEN a.Name = 'Message ' THEN fa.Created END)
        ,LikesContent = MAX(CASE WHEN a.Name = 'LikesContent ' THEN fa.Created END)
        ,JoinsGroup = MAX(CASE WHEN a.Name = 'JoinsGroup ' THEN fa.Created END)
        ,M1 = MAX(CASE WHEN da.Name = 'M1' THEN das.Created END)
        ,M2 = MAX(CASE WHEN da.Name = 'M2 ' THEN das.Created END)
        ,M3 = MAX(CASE WHEN da.Name = 'M3 ' THEN das.Created END)
        ,M4 = MAX(CASE WHEN da.Name = 'M4 ' THEN das.Created END)
    FROM fan f
    JOIN dbo.ProfileFan pf
        ON pf.FanId = f.FanId
    JOIN dbo.LinkedInProfile lip
        ON lip.Id = pf.ProfileId
    JOIN dbo.FanActivities fa
        ON fa.ProfileFanId = pf.Id
    JOIN Activities a
        ON a.Id = fa.ActivityId
    JOIN dbo.DeliveryActions das
        ON das.ProfileFanId = pf.Id
    JOIN dbo.DeliveryAction da
        ON da.Id = das.ActivityId
    GROUP BY f.Name, f.info, lip.Client
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-19
      • 2014-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多