PIVOT with dynamic columns and JOINS 5+ tables

。_饼干妹妹 提交于 2019-12-11 06:13:34

问题


This is an extension of a question posted by me earlier which can be found here : Previous Question

Now i have 2 more tables that are also connected to ProfileFan tracking the Activities of the Fan(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             |        
    ------------------------

The output of the query should look like this.

    -------------------------------------------------------------------------------------------------------------------------------------------------------
    | 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 |
    ---------------------------------------------------------------------------------------------------------------------------------------------------

I need to insert the data from a query for one fan in a single row instead multiple for every row that gives me the joins. So far as suggested by stackoverflow user i have come to solution to do it for only the LinkedInProfile by using PIVOT and dynamic query.

I Have also created a simulation here https://rextester.com/live/NYYK67222

I need to make the appropriate joins with the FanActivities and DeliveryActions Table On top of the joins so far and put the data in a single row per FAN!

So 1 FAN is under 2 LinkedInProfiles -> This creates 2 ProfileFansId. All the profileFans have many FanActivities and Many DeliveryActions.

I know that i need to use PIVOT with dynamic columns here. But its all new to me.


回答1:


Since your desired result is different from your sample data on rexter, I just modified few data in FanActivities & DeliveryActions tables.

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);

And your query would be

;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

And the result I got

+---------+-------+---------+-------------------+-------------------+-------------+------------+--------------+------------+------------+------------+------------+------------+
| 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:


There's some discrepancies between the sample code in the post and your rextester sample (for example, DeliveryActions.ProfileFanId in your post appears to reference Fan.FanId , but in the rextester sample it references ProfileFan.Id). My answer is built off of your rextester sample.

My personal preference is to not do multiple pivots if I don't have to and, instead, use a cross tab query... it's just easier for me to look at and comprehend rather than having multiple layers of pivots.

You can see this in 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


来源:https://stackoverflow.com/questions/55516285/pivot-with-dynamic-columns-and-joins-5-tables

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