PIVOT с динамическими столбцами и таблицами JOINS 5+ - PullRequest
1 голос
/ 04 апреля 2019

Это расширение вопроса, отправленного мной ранее, который можно найти здесь: Предыдущий вопрос

Теперь у меня есть еще 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, я пришел к решению сделать это только для LinkedInProfile, используя PIVOT и динамический запрос.

Я также создал симуляцию здесь https://rextester.com/live/NYYK67222

Мне нужно сделать соответствующие объединения с таблицей FanActivities и DeliveryActions. На данный момент поверх объединений и поместить данные в одну строку.на одного ВЕНТИЛЯТОРА!

Таким образом, 1 ВЕНТИЛЯТОР меньше 2 LinkedInProfiles -> Это создает 2 ProfileFansId.Все поклонники профиля имеют много FanActivities и много DeliveryActions.

Я знаю, что мне нужно использовать PIVOT с динамическими столбцами здесь.Но это все новое для меня.

Ответы [ 2 ]

2 голосов
/ 04 апреля 2019

Поскольку желаемый результат отличается от данных примера на 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 |
+---------+-------+---------+-------------------+-------------------+-------------+------------+--------------+------------+------------+------------+------------+------------+
1 голос
/ 04 апреля 2019

Есть некоторые несоответствия между примером кода в сообщении и вашим примером реэкстестера (например, DeliveryActions.ProfileFanId в вашем посте ссылается на Fan.FanId, но в примере реэкстера он ссылается на ProfileFan.Id).Мой ответ основан на вашем образце ректестера.

Мое личное предпочтение - не делать несколько сводок, если мне не нужно, и вместо этого использовать перекрестный запрос ... мне просто легче смотреть и понимать, а не иметь несколько слоевpivots.

Вы можете увидеть это в rextester здесь .

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