PIVOT dynamically, Returned results from JOIN of two tables

前端 未结 1 1005
伪装坚强ぢ
伪装坚强ぢ 2020-12-03 16:18

What I thought was a fairly simple query seems to be a bit more tricky then what I anticipated.

I have two tables. With One-to-many relation. What I am trying to do

相关标签:
1条回答
  • 2020-12-03 16:58

    Maybe I am missing something but you should be able to PIVOT the data but you will need to implement row_number() to help generate the columns.

    The key will be to use a query similar to:

    SELECT  ONE.UserID,
      ONE.Episode,
      ONE.Value,
      TWO.Details,
      'Details'
        +cast(row_number() over(partition by one.userid, one.episode
                               order by two.details) as varchar(10)) seq
    FROM TABLE1 ONE 
    INNER JOIN TABLE2 Two
      ON ONE.UserID = TWO.UserID 
    AND ONE.Episode = TWO.Episode
    

    This will create a unique sequence for the new columns names, then you can apply the PIVOT:

    select userid, episode,
      value,
      details1,
      details2
    from
    (
      SELECT  ONE.UserID,
        ONE.Episode,
        ONE.Value,
        TWO.Details,
        'Details'
          +cast(row_number() over(partition by one.userid, one.episode
                                  order by two.details) as varchar(10)) seq
      FROM TABLE1 ONE 
      INNER JOIN TABLE2 Two
        ON ONE.UserID = TWO.UserID 
      AND ONE.Episode = TWO.Episode
    ) d
    pivot
    (
      max(details)
      for seq in (Details1, Details2)
    ) piv;
    

    See SQL Fiddle with Demo. Then you can convert this to dynamic SQL:

    DECLARE @cols AS NVARCHAR(MAX),
        @query  AS NVARCHAR(MAX)
    
    select @cols = STUFF((SELECT ',' + QUOTENAME('Details'+cast(seq as varchar(10))) 
                        from 
                        (
                          select 
                            row_number() over(partition by one.userid, one.episode
                                                    order by two.details) seq
                            FROM TABLE1 ONE 
                            INNER JOIN TABLE2 Two
                              ON ONE.UserID = TWO.UserID 
                            AND ONE.Episode = TWO.Episode
                        ) d
                        group by seq
                        order by seq
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    set @query = 'SELECT userid, episode, value, ' + @cols + ' 
                from 
                (
                 SELECT  ONE.UserID,
                    ONE.Episode,
                    ONE.Value,
                    TWO.Details,
                    ''Details''
                      +cast(row_number() over(partition by one.userid, one.episode
                                              order by two.details) as varchar(10)) seq
                  FROM TABLE1 ONE 
                  INNER JOIN TABLE2 Two
                    ON ONE.UserID = TWO.UserID 
                  AND ONE.Episode = TWO.Episode
                ) x
                pivot 
                (
                    max(details)
                    for seq in (' + @cols + ')
                ) p '
    
    execute sp_executesql @query;
    

    See SQL Fiddle with Demo. Giving you the result:

    | USERID | EPISODE |     VALUE |  DETAILS1 |  DETAILS2 |
    |--------|---------|-----------|-----------|-----------|
    |      1 |       1 | VALUE 1-1 | Details 1 | Details 2 |
    |      1 |       2 | VALUE 1-2 | Details 1 | Details 2 |
    
    0 讨论(0)
提交回复
热议问题