【问题标题】:PIVOT dynamically, Returned results from JOIN of two tables动态 PIVOT,从两个表的 JOIN 中返回结果
【发布时间】:2014-02-14 17:24:48
【问题描述】:

我认为是一个相当简单的查询似乎比我预期的要复杂一些。

我有两张桌子。具有一对多关系。我想要做的是表二返回的任何记录,我希望它位于单独的列中。我已经设法在以下查询中使用相对较小的数据并知道第二个表返回的内容。

样本数据

DECLARE @TABLE1 TABLE(UserID INT,Episode INT ,[Value] VARCHAR(100))
INSERT INTO @TABLE1 VALUES
(1, 1,'VALUE 1-1'),(1, 2,'VALUE 1-2')

DECLARE @TABLE2 TABLE(UserID INT,Episode INT ,[Details] VARCHAR(100))
INSERT INTO @TABLE2 VALUES
(1, 1,'Details 1'),(1, 1,'Details 2'),(1, 2,'Details 1'),(1, 2,'Details 2') 

简单加入

SELECT  ONE.UserID
      , ONE.Episode
      , ONE.Value
      , TWO.Details 
FROM @TABLE1 ONE INNER JOIN @TABLE2 Two
ON ONE.UserID = TWO.UserID 
AND ONE.Episode = TWO.Episode

╔════════╦═════════╦═══════════╦═══════════╗
║ UserID ║ Episode ║   Value   ║  Details  ║
╠════════╬═════════╬═══════════╬═══════════╣
║      1 ║       1 ║ VALUE 1-1 ║ Details 1 ║
║      1 ║       1 ║ VALUE 1-1 ║ Details 2 ║
║      1 ║       2 ║ VALUE 1-2 ║ Details 1 ║
║      1 ║       2 ║ VALUE 1-2 ║ Details 2 ║
╚════════╩═════════╩═══════════╩═══════════╝

在这种情况下,我想PIVOT 详细信息列。我设法用一个非常简单的 PIVOT 查询来完成,如下所示

PIVOT 查询

SELECT * FROM
(
SELECT  ONE.UserID
      , ONE.Episode
      , ONE.Value
      , TWO.Details 
FROM @TABLE1 ONE INNER JOIN @TABLE2 Two
ON ONE.UserID = TWO.UserID AND ONE.Episode = TWO.Episode)Q
PIVOT (MAX(Details)
       FOR Details
       IN ([Details 1], [Details 2]))p

╔════════╦═════════╦═══════════╦═══════════╦═══════════╗
║ UserID ║ Episode ║   Value   ║ Details 1 ║ Details 2 ║
╠════════╬═════════╬═══════════╬═══════════╬═══════════╣
║      1 ║       1 ║ VALUE 1-1 ║ Details 1 ║ Details 2 ║
║      1 ║       2 ║ VALUE 1-2 ║ Details 1 ║ Details 2 ║
╚════════╩═════════╩═══════════╩═══════════╩═══════════╝

这正是我想要的,从名为Details 1Details 2Details 3 等的列中的表二返回的所有记录...

在这种情况下它起作用了,因为重新调整的数据本身是字符串,如 "Details 1" 、 "Details 2" 和 "Details 3"。

但是当我不知道 table2 将返回多少行以及我正在努力调整的数据时。

还有一件更重要的事情是,从表二返回的数据是Large Text values,由几列连接而成。

我尝试遵循 thisthisthis 问题中给出的逻辑,但没有乐趣。

非常感谢您对正确方向的任何帮助,在此先感谢您。

【问题讨论】:

  • 您必须编写动态 SQL 才能在 SQL 中处理这种情况。
  • 我见过的所有问题,人们使用动态 sql 来实现这个结果,动态 sql 依赖于从连接返回的数据,在我的情况下,返回的数据是一个长文本值,真的想不到在我的数据透视查询中使用该返回文本的方法:S
  • 如果您不想使用长文本作为列名,您想使用哪些列名?只是像col1col2 这样生成的东西?
  • @FrankPl 是的,像 Details 1 Details 2 ... Details 3 或类似的东西
  • 您的客户能否处理不断变化的结果集结构,例如拥有 e. G。一个电话有两个详细信息列,下次有五个?

标签: sql sql-server sql-server-2008 pivot


【解决方案1】:

也许我遗漏了一些东西,但您应该能够 PIVOT 数据,但您需要实现 row_number() 来帮助生成列。

关键是使用类似于以下的查询:

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

这将为新列名称创建一个唯一序列,然后您可以应用 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;

SQL Fiddle with Demo。然后你可以把它转换成动态 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;

SQL Fiddle with Demo。给你结果:

| USERID | EPISODE |     VALUE |  DETAILS1 |  DETAILS2 |
|--------|---------|-----------|-----------|-----------|
|      1 |       1 | VALUE 1-1 | Details 1 | Details 2 |
|      1 |       2 | VALUE 1-2 | Details 1 | Details 2 |

【讨论】:

  • 感谢一百万 bluefeet 你是超级明星 :)
猜你喜欢
  • 2013-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-29
  • 2018-06-29
  • 1970-01-01
相关资源
最近更新 更多