【问题标题】:SQLSERVER Select rows as columns even if there is no enough rowsSQL SERVER 选择行作为列,即使没有足够的行
【发布时间】:2015-03-22 06:11:37
【问题描述】:

我在构建查询时遇到问题。在stackoverflow上搜索后,我认为我需要一个交叉表。但我不知道这到底是什么。我认为如果我向您展示我的问题的简化版本会更快。如果您能指出正确的方向,我会很高兴。

这是数据示例:

ColumnIDToGroup  Value
-----------------------
  1              AAAA
  1              BBBB
  2              AAAA
  2              BBBB
  2              CCCC

我需要构建一个查询来获取这种格式的数据:

ColumnIDToGroup  Value1  Value2   Value3  Value4  Value5
------------------------------------------------------------
  1              AAAA     BBBB   'Empty'  'Empty' 'Empty'
  2              AAAA     BBBB    CCCC    'Empty' 'Empty'

作为一种解决方法,我可以接受这个输出,如果它易于构建(当一个值不为空时,它总是具有相同的大小)

ColumnIDToGroup      ValueConcat  
-------------------------------------
  1              AAAABBBB************
  2              AAAABBBBCCCC********

【问题讨论】:

    标签: sql-server-2008 crosstab


    【解决方案1】:

    示例表

    CREATE TABLE #TEMP(ColumnIDToGroup INT,Value VARCHAR(30))
    
    INSERT INTO #TEMP
    SELECT  1,             'AAAA'
    UNION ALL
     SELECT   1,              'BBBB'
    UNION ALL
     SELECT   2,              'AAAA'
    UNION ALL
     SELECT   2,              'BBBB'
    UNION ALL
    SELECT    2,              'CCCC'
    

    现在从表中选择行,为 Value1、Value2 等创建一列,并通过 UNION all 为 Value4、Value5 选择额外的列,并将文本设置为 Empty。

    SELECT *,
    'Value'+CAST(ROW_NUMBER() OVER(PARTITION BY  ColumnIDToGroup ORDER BY VALUE)AS VARCHAR(3)) COL
    INTO #NEWTABLE
    FROM #TEMP
    UNION ALL
    SELECT 1,'Empty','Value3'
    UNION ALL
    SELECT 2,'Empty','Value3'
    UNION ALL
    SELECT 1,'Empty','Value4'
    UNION ALL
    SELECT 2,'Empty','Value4'
    UNION ALL
    SELECT 1,'Empty','Value5'
    UNION ALL
    SELECT 2,'Empty','Value5'
    

    现在获取枢轴的列

    DECLARE @cols NVARCHAR (MAX)
    
    SELECT @cols = COALESCE (@cols + ',[' + COL + ']', '[' + COL + ']')
                   FROM    (SELECT DISTINCT COL FROM #NEWTABLE) PV 
                   ORDER BY COL
    

    现在旋转查询

    DECLARE @query NVARCHAR(MAX)
    SET @query = 'SELECT * FROM 
                 (
                     SELECT *   
                     FROM #NEWTABLE
                 ) x
                 PIVOT 
                 (
                     MIN(VALUE)
                     FOR COL IN (' + @cols + ')
                ) p
                ORDER BY ColumnIDToGroup;' 
    
    EXEC SP_EXECUTESQL @query
    

    如果你想要第二个指定的格式,你可以使用下面的查询

    ;WITH CTE AS
    (
        SELECT *        
        FROM #TEMP
        UNION ALL
        SELECT 1,'****'
        UNION ALL
        SELECT 2,'****'
        UNION ALL
        SELECT 1,'****'
        UNION ALL
        SELECT 2,'****'
        UNION ALL
        SELECT 1,'****'
        UNION ALL
        SELECT 2,'****'
        UNION ALL
        SELECT 1,'****'
        UNION ALL
        SELECT 1,'***'
    )
    SELECT  DISTINCT C2.ColumnIDToGroup,  
    -- Convert to single row for each ColumnIDToGroup
            SUBSTRING(
            (SELECT ' ' + CTE.VALUE
            FROM CTE 
            WHERE C2.ColumnIDToGroup=ColumnIDToGroup
            ORDER BY 
            CASE WHEN CTE.VALUE = 'AAAA' THEN 1
                 WHEN CTE.VALUE = 'BBBB' THEN 2
                 WHEN CTE.VALUE = 'CCCC' THEN 3
            ELSE 4
            END
            FOR XML PATH('')),2,200000) ValueConcat 
            FROM CTE C2
    

    【讨论】:

    • 如有任何更改,请随时提出要求。 @Rumpel
    • 首先感谢您的帮助。我看到的唯一问题是UNION。这背后的想法是创建一个视图或存储过程以最简单的方式查阅数据。我不知道表#TEMP 中的数据,因为它会发生变化。这背后的应用程序不断插入、更新删除行。所以我不知道如何动态地构建联合。我的意思是,如果我在存储过程中使用您的代码,然后,我插入一行(例如:ID:1,Value:CCCC),我得到 2 行具有相同值 en COL。 (在下一条评论中继续)
    • 另外,如果我删除一行(例如 ID:1,Value:AAAA),我不会有任何带有 Value1 的 COL。但是我看到了这背后的想法,我认为,多亏了你,我可以自己解决最后一个问题:D
    • 是的。对于给定的样本,它将起作用。如果表中的值不断变化,你必须做'Empty'和**** dynamic。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 2016-12-15
    • 1970-01-01
    相关资源
    最近更新 更多