【问题标题】:sql server query - pivot after n columnssql server 查询 - 在 n 列之后进行透视
【发布时间】:2013-02-01 11:46:33
【问题描述】:

我有一个包含 N 列的表格:

TABLE:
TB_SAMPLE

COLUMNS:

VALUE_A
COUNT_A
VALUE_B
COUNT_B
VALUE_C
COUNT_C
VALUE_D
COUNT_D
VALUE_E
COUNT_E
VALUE_F
COUNT_F
VALUE_G
COUNT_G
VALUE_H
COUNT_H
VALUE_I
COUNT_I

我想这样返回:

'Value', 'Count'
A, 1 -- this is the first and the second column
B, 3 -- this is the third and the fourth column
C, 4 -- this is the fifth and sixth column

等等。我已经尝试使用 UNION ALL 子句进行多项选择,但是由于我要返回很多记录,所以速度不是那么快。有没有更好的方法来“透视”这个表的 2 列?

谢谢。

【问题讨论】:

  • 如何计算每个列或值 A 的计数?
  • 你能从你的表中发布一些示例数据吗?很难说出想要的结果是什么。
  • @techdo 这是另一个保存此信息的应用程序
  • @bluefeet 例如,我在一个表中有 30 列。我想每两列切换一次。 (第一列和第二列连续,第三和第四列在第二列,依此类推)。

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


【解决方案1】:

这也可以使用CROSS APPLYVALUES 语句来执行:

SELECT vals, counts
FROM temp t
CROSS APPLY 
(
    VALUES
        (value_a, count_a),
        (value_b, count_b),
        (value_c, count_c),
        (value_d, count_d),
        (value_e, count_e),
        (value_f, count_f),
        (value_g, count_g),
        (value_h, count_h)
) x (vals, counts);

SQL Fiddle with Demo

这里有一篇文章解释了这是如何完成的(需要注册):

http://www.sqlservercentral.com/articles/CROSS+APPLY+VALUES+UNPIVOT/91234/

【讨论】:

  • 不错的解决方案。虽然,您发布的链接需要注册,这有点痛苦......
【解决方案2】:

您可以 UNPIVOT,然后 PIVOT 数据,它可能会表现得更好:

DECLARE @T TABLE 
(   VALUE_A INT, COUNT_A INT, VALUE_B INT, COUNT_B INT, VALUE_C INT, COUNT_C INT, VALUE_D INT, COUNT_D INT, VALUE_E INT, 
    COUNT_E INT, VALUE_F INT, COUNT_F INT, VALUE_G INT, COUNT_G INT, VALUE_H INT, COUNT_H INT, VALUE_I INT, COUNT_I INT
);
INSERT @T VALUES (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);

WITH D AS
(   SELECT  Category = SUBSTRING(B, 7, LEN(B)), [Type] = 'Value', A
    FROM    @T
            UNPIVOT 
            (   A
                FOR B IN ([VALUE_A], [VALUE_B], [VALUE_C], [VALUE_D], [VALUE_E], [VALUE_F], [VALUE_G], [VALUE_H], [VALUE_I])
            ) upvt
    UNION ALL
    SELECT  Category = SUBSTRING(B, 7, LEN(B)), [Type] = 'Count', A
    FROM    @T
            UNPIVOT 
            (   A
                FOR B IN ([COUNT_A], [COUNT_B], [COUNT_C], [COUNT_D], [COUNT_E], [COUNT_F], [COUNT_G], [COUNT_H], [COUNT_I])
            ) upvt
)
SELECT  *
FROM    D
        PIVOT
        (   SUM(A)
            FOR [Type] IN ([Value], [Count])
        ) pvt;

如果需要,您也可以通过在系统视图中查询列名来动态执行此操作。

附录

刚刚意识到这可以通过联接而不是 UNION 和 PIVOT 来实现,我想联接会在删除 PIVOT 操作时表现得更好。我仍然建议测试两者,看看哪个最适合您的数据。

WITH Val AS
(   SELECT  Category = SUBSTRING(B, 7, LEN(B)), A
    FROM    @T
            UNPIVOT 
            (   A
                FOR B IN ([VALUE_A], [VALUE_B], [VALUE_C], [VALUE_D], [VALUE_E], [VALUE_F], [VALUE_G], [VALUE_H], [VALUE_I])
            ) upvt
), Co AS
(   SELECT  Category = SUBSTRING(B, 7, LEN(B)), A
    FROM    @T
            UNPIVOT 
            (   A
                FOR B IN ([COUNT_A], [COUNT_B], [COUNT_C], [COUNT_D], [COUNT_E], [COUNT_F], [COUNT_G], [COUNT_H], [COUNT_I])
            ) upvt
)
SELECT  val.Category,
        [Value] = val.A,
        [Count] = co.A
FROM    val
        INNER JOIN co
            ON co.Category = val.Category;

【讨论】:

    【解决方案3】:

    这是另一种方法(如果我正确理解了您的问题)

    declare @table table
    (
    value_a varchar(10),
    count_a int,
    value_b varchar(10),
    count_b int,
    value_c varchar(10),
    count_c int,
    value_d varchar(10),
    count_d int,
    value_e varchar(10),
    count_e int,
    value_f varchar(10),
    count_f int,
    value_g varchar(10),
    count_g int,
    value_h varchar(10),
    count_h int
    )
    
    Insert Into @table
    Select  'value a',675,
            'value b',646,
            'value c',13,
            'value d',22,
            'value e',768,
            'value f',223,
            'value g',66,
            'value h',55
    
    
    SELECT  vals,
            counts
    FROM 
       (
        SELECT  *
       FROM @table
        ) p
    UNPIVOT
       (vals FOR cols IN 
          ([value_a],[value_b],[value_c],[value_d], [value_e],[value_f],[value_g],[value_h])
    )AS unpvtValues
    Unpivot 
        (
            counts for counters in ([count_a],[count_b],[count_c], [count_d],[count_e],[count_f],[count_g],[count_h])
        ) as unpvtCounts
    where Right(cols, 2) = right(counters, 2)
    

    编辑

    如果你想使用一些动态 SQL,那么你可以使用这个选项(这会在你的数据库中创建一个适当的表,而不是使用表变量)

    create  Table  dbo.TempTable
    (
    value_a varchar(10),
    count_a int,
    value_b varchar(10),
    count_b int,
    value_c varchar(10),
    count_c int,
    value_d varchar(10),
    count_d int,
    value_e varchar(10),
    count_e int,
    value_f varchar(10),
    count_f int,
    value_g varchar(10),
    count_g int,
    value_h varchar(10),
    count_h int
    )
    
    Insert Into dbo.TempTable
    Select  'value a',675,
            'value b',646,
            'value c',13,
            'value d',22,
            'value e',768,
            'value f',223,
            'value g',66,
            'value h',55
    
    
    Declare @ValueCols varchar(max),
            @CountCols varchar(max),
            @sql varchar(max)
    
    
    Select @ValueCols = Coalesce(@ValueCols + ', ','') + '[' + Column_Name +']'
    From INFORMATION_SCHEMA.COLUMNS
    Where TABLE_NAME  = 'TempTable'
    And COLUMN_NAME Like 'Value%'
    
    Select @CountCols = Coalesce(@CountCols + ', ','') + '[' + Column_Name +']'
    From INFORMATION_SCHEMA.COLUMNS
    Where TABLE_NAME  = 'TempTable'
    And COLUMN_NAME Like 'Count%'
    
    
    Set @sql = 'SELECT  vals,
            counts
    FROM 
       (
        SELECT  *
       FROM dbo.TempTable
        ) p
        UNPIVOT
       (vals FOR cols IN 
          (' + @ValueCols +')
    )AS unpvtValues
    Unpivot 
        (
            counts for counters in (' + @CountCols + ')
        ) as unpvtCounts
    where Right(cols, 2) = right(counters, 2)'
    
    
    Execute (@sql)
    
    drop table TempTable
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-06
      • 2017-09-02
      • 1970-01-01
      • 2012-11-13
      • 1970-01-01
      • 2011-12-28
      相关资源
      最近更新 更多