【问题标题】:SQL query for group by result in different column [closed]SQL查询分组结果在不同的列[关闭]
【发布时间】:2020-02-19 14:07:58
【问题描述】:

我的表格有 2 列

Column1 Value
   A     10 
   B     20 
   C     11
   A     40 
   B     30 
   C     22

我想要类似的结果

Column1 Value1 Value2
A       10      40
B       20      30
C       11      22

是否有任何查询或存储过程来获得这样的输出

【问题讨论】:

  • 问题不清楚。您有两列,请明确第 1 列和第 2 列中有哪些值
  • 如果有一行(A, 42)(B, 25)
  • 如果你添加更多的数据点就很清楚了。现在看起来你想要最小值和最大值。
  • 亲爱的,我已经删除了我的答案,因为你在评论中写了你想要的 Value1、Valu2、Value3 等等。也许您可以使用枢轴功能

标签: sql sql-server pivot


【解决方案1】:

如果有超过 2 个 Value 列,则 MIN 和 MAX 将不起作用。

然后您可以使用 ROW_NUMBER 计算编号值,并在 PIVOT 中使用它

SELECT *
FROM
(
    SELECT Column1, [Value]
    , Col = CONCAT('Value', ROW_NUMBER() OVER (PARTITION BY Column1 ORDER BY [Value]))
    FROM YourTable
) Src
PIVOT (
    MAX([Value])
     -- add more columns here
    FOR Col IN (Value1, Value2)
) Pvt

【讨论】:

    【解决方案2】:

    如果您不确定每个 Column1 会有多少个值,则必须执行动态 SQL。

    改编@LukStorms 上面的优秀答案:

    IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL
        DROP TABLE #MyTable
    
    
    create table #MyTable (c nvarchar(1), v int)
    
    insert into #MyTable
    select 'A',10
    union select 'B',20
    union select 'C',11
    union select 'A',40
    union select 'B',30
    union select 'C',22
    union select 'A',60
    union select 'C',28
    union select 'C',150
    
    declare @s varchar(max), @maxVals int, @i int = 1
    
    select @maxVals = max(ct) from (select c,count(*) as ct from #MyTable group by c) as x
    
    set @s = 'SELECT *
    FROM
    (
        SELECT c as Column1, v
        , Col = CONCAT(''Value'', ROW_NUMBER() OVER (PARTITION BY c ORDER BY v))
        FROM #MyTable
    ) Src
    PIVOT (
        MAX(v)
        FOR Col IN ('
    
    while @i <= @maxVals
    begin
    
    set @s = @s + 'Value' + cast(@i as varchar)
    
    if @i < @maxVals
         set @s = @s + ', '
    
    set @i = @i +1
    end
    
    set @s = @s + ')
    ) Pvt'
    
    exec(@s)
    

    请注意,SQL 不一定会保持插入值的顺序,除非您使用标识列并对其进行排序。此外,如果 column1 有多个相同的值,它将忽略重复的值。

    希望对您有所帮助,并感谢 @LukStorms 的初步工作

    【讨论】:

      【解决方案3】:

      也可以如下动态完成,因为您不确定通过修改@LukStorms 答案的列数

      create table #MyTable (Column1 VARCHAR(2), [Value] INT)
      insert into #MyTable values
      ('A',10),('B',20),('C',11),
      ('A',40), ('B',30), ('C',22)
      
      
      
       DECLARE @cols AS NVARCHAR(MAX),
              @query  AS NVARCHAR(MAX);
      
      SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(CONCAT('Value', ROW_NUMBER() OVER (PARTITION BY Column1 ORDER BY [Value]))) 
                  FROM #MyTable
                  FOR XML PATH(''), TYPE
                  ).value('.', 'NVARCHAR(MAX)') 
              ,1,1,'')
      
      set @query =  'SELECT 
                      * 
                    FROM
                  ( SELECT Column1, [Value],
                  CONCAT(''Value'', ROW_NUMBER() OVER (PARTITION BY Column1 ORDER BY [Value])) AS ColValue
                      FROM #MyTable
                  ) Src
                  PIVOT (
                      MAX([Value]) FOR ColValue IN ('+@cols+')  
      ) Pvt'
      
       exec(@query)
      
       drop table #MyTable
      

      【讨论】:

        【解决方案4】:

        您需要DynamicSql + Pivot操作。我不知道任何其他方法。

        下面的查询会给你你想要的。

        DROP TABLE tmptbl
        GO
        SELECT * ,
            'Value' + (CONVERT(NVARCHAR(MAX), ROW_NUMBER() OVER (PARTITION BY [Column1] ORDER BY Column1,[Value]))) [ValueColumn]
        INTO tmptbl
        FROM (
        SELECT 'A' [Column1],10 [Value]
        UNION ALL
        SELECT 'A' [Column1],20 [Value]
        UNION ALL
        SELECT 'A' [Column1],30 [Value]
        UNION ALL
        SELECT 'B' [Column1],40 [Value]
        UNION ALL
        SELECT 'B' [Column1],50 [Value]
        UNION ALL
        SELECT 'B' [Column1],60 [Value]
        UNION ALL
        SELECT 'B' [Column1],70 [Value]
        ) tbl
        GO
        DECLARE @Vals NVARCHAR(MAX)
        SET @Vals = N''
        SELECT @Vals = STUFF((SELECT ', ' + QUOTENAME('Value' + CONVERT(NVARCHAR(MAX), ROW_NUMBER() OVER (ORDER BY [Valuecolumn])))
                        FROM tmptbl
                        GROUP BY [Valuecolumn]
                        FOR XML PATH ('')),1,1,'')
        SELECT @vals
        
        DECLARE @strsql NVARCHAR(MAX) = ' SELECT [Column1],' + @vals + ' 
                                          FROM (
                                             SELECT [Column1],[Value],[ValueColumn]
                                             FROM tmptbl
                                               ) t
                                          PIVOT (
                                          AVG([Value])
                                          FOR [ValueColumn] IN (' + @Vals + ')) As p'
        EXEC (@strsql)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-16
          • 2016-02-16
          相关资源
          最近更新 更多