【问题标题】:SQL query unknown rows into columnsSQL将未知行查询成列
【发布时间】:2014-05-28 10:13:14
【问题描述】:

我问了这个问题,它被标记为与How to pivot unknown number of columns & no aggregate in SQL Server? 重复,但这个答案对我没有帮助。

我有一个看起来像这样的数据表,其中包含未知数量的行和值。

RecID     Name      Value
1         Color     Red
2         Size      Small
3         Weight    20lbs
4         Shape     Square

我需要一个查询来返回这样的数据,为每一行构建一个列。除了列标题“名称”和“值”之外,我无法对任何内容进行硬编码。

Color     Size     Weight     Shape
Red       Small    20lbs      Square

这是我到目前为止部分工作的内容:

INSERT INTO @Table VALUES
(1,'Color' ,'Red'),
(2,'Size'  ,'Small'),
(3,'Weight','20lbs'),
(4,'Shape' ,'Square')

 ;with mycte
 as
 (
SELECT rn,cols,val
FROM   (SELECT  row_number() over(order by Name) rn, Name, Value
        FROM  @Table) AS src1
UNPIVOT (val FOR cols
IN ( [Name], [Value])) AS unpvt
 )

SELECT *
FROM   (SELECT rn,cols,val
        FROM   mycte) AS src2 PIVOT
( Max(val) FOR rn IN ([1], [2], [3])) AS pvt

返回:

cols    1   2   3
Name    Color   Shape   Size
Value   Red Square  Small

这有两个我似乎无法解决的问题。

  1. 我不需要列标题和包含 cols、Name、Value 的第一列。
  2. 不知道如何在不指定 [x] 标识符的情况下让它为每一行构建一列。

任何指导都会很棒我已经坚持了一段时间了。

【问题讨论】:

    标签: sql sql-server pivot


    【解决方案1】:

    到目前为止,我已经达到了以下代码,希望对您有所帮助,

    当前输出为

    Color   Shape   Size    Weight
    Red     NULL    NULL    NULL
    NULL    NULL    Small   NULL
    NULL    NULL    NULL    20lbs
    NULL    Square  NULL    NULL
    
    Create table DyTable  
    (
        tid int,
        Name varchar(20),
        Value varchar(20)
    )
    
    INSERT INTO DyTable VALUES
    (1,'Color' ,'Red'),
    (2,'Size'  ,'Small'),
    (3,'Weight','20lbs'),
    (4,'Shape' ,'Square')
    
    DECLARE @Cols NVARCHAR(MAX);
    DECLARE @Cols1 NVARCHAR(MAX);
    
    SELECT @Cols =  STUFF((
                        SELECT DISTINCT ', ' +  QUOTENAME(Name) 
                        FROM DyTable
                        FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,'')
                    ,@Cols1 =  STUFF((
                        SELECT DISTINCT ', max(' +  QUOTENAME(Name) + ') as ' + Name
                        FROM DyTable
                        FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,'')
    
    
    DECLARE @Sql NVARCHAR(MAX)
    Select @Cols
    
    SET @Sql  = 'Select '+ @Cols1 +'
                from (SELECT ' + @Cols +   '
                FROM DyTable t
                PIVOT (MAX(Value)
                        FOR Name 
                        IN (' + @Cols + ')
                        )P)a'
    
    EXECUTE sp_executesql @Sql
    

    【讨论】:

    • 我建议您仍然使用像row_number() 这样的窗口函数,这样您仍然可以为每个名称返回多行。如果你不这样做,那么你只会返回每一行。
    • @bluefeet,我不明白你在说什么,但我已经更新了我的答案。这可能不是最好的方法,但它确实有效。请让我知道我们是否可以制定更正确和更简短的方法。
    • 看看这个答案 - stackoverflow.com/questions/22968734/… - 问题是当你聚合一个字符串时,你只会返回一行数据。应用诸如 row_number 之类的窗口函数将允许返回多行名称等。
    【解决方案2】:
    declare @collist nvarchar(max)
    SET @collist = stuff((select distinct ',' + QUOTENAME(name) 
                FROM #t -- your table here
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
            ,1,1,'')
    
    declare @q nvarchar(max)
    set @q = '
    select * 
    from (
        select rn, name, Value
            from (
            select *, row_number() over (partition by name order by RecID desc) as rn
            from #t -- your table here
        ) as x
    ) as source
    pivot (
        max(Value)
        for name in (' + @collist + ')
    ) as pvt
    '
    
    exec (@q)
    

    【讨论】:

    • 这很完美!非常感谢你,我已经走了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多