分享
三行代码  ›  专栏  ›  技术社区  ›  Farhät

旋转数据库表

  •  2
  • Farhät  · 技术社区  · 1 周前

    ╔══════════════════════╗
    ║ Name   Quarter Sales ║
    ╠══════════════════════╣
    ║ Joe    Q1      700   ║
    ║ Joe    Q2      650   ║
    ║ Joe    Q3      660   ║
    ║ Bill   Q1      500   ║
    ║ Bill   Q2      520   ║
    ║ Bill   Q3      550   ║
    ║ Bob    Q2      200   ║
    ║ Bob    Q3      250   ║
    ╚══════════════════════╝
    

    我需要把它转换成如下格式。在这里,每个季度的不同值变成一列,每个季度的销售额是每个销售人员对应列的值。

    ╔══════════════════════╗
    ║ Name   Q1   Q2   Q3  ║
    ╠══════════════════════╣
    ║ Joe    700  650  660 ║
    ║ Bill   500  520  550 ║
    ║ Bob         200  250 ║
    ╚══════════════════════╝
    

    这在SQL中可能吗?我使用的是SQL Server,但如果可能的话,我更喜欢纯SQL。

    我们不知道前面四分之一列中的值,也就是说,我们不仅限于Q1/Q2/Q3等。假设用户可以输入Q1、Quarter 1或任何他们喜欢的其他内容。

    2 回复  |  直到 1 周前
        1
  •  2
  •   D-Shih    1 周前

    您可以尝试使用聚合条件 SUM 具有 CASE WHEN

    SELECT Name,
           SUM(CASE WHEN Quarter = 'Q1' THEN Sales ELSE 0 END) 'Q1',
           SUM(CASE WHEN Quarter = 'Q2' THEN Sales ELSE 0 END) 'Q2',
           SUM(CASE WHEN Quarter = 'Q3' THEN Sales ELSE 0 END) 'Q3'
    FROM T
    GROUP BY Name
    
        2
  •  2
  •   ZHui    1 周前

    我建议使用 PIVOT

    通过查看上面的评论,您确实希望在第一季度, 问题2。。。动态地,因为您可能没有季度的特定值。

    在这里我更新了我的答案,请试试看。

    替换 PivotSample TableName

    IF OBJECT_ID('tempdb..##TEMP_TBL') IS NOT NULL
    DROP TABLE ##TEMP_TBL
    
    --GET all pivoted column -> [Q1], [Q12]...
    DECLARE @pivot_col AS NVARCHAR(MAX)
    ;WITH distinct_col AS
    (
        SELECT DISTINCT [Quarter]
        FROM PivotSample
    )
    SELECT @pivot_col = COALESCE(@pivot_col + ',', '') + QUOTENAME([Quarter])
    FROM distinct_col
    
    --Generate query, to pivot the data given
    DECLARE @query AS NVARCHAR(MAX)
    SET @query = 
        N'SELECT [Name], ' + @pivot_col + ' ' +
        'INTO ##TEMP_TBL
        FROM PivotSample
        PIVOT
        (
            SUM(Sales)
            FOR [Quarter] IN ( ' + @pivot_col + ' )
        ) AS pvt'
    
    --Execute query, to insert result into ##TEMP_TBL
    EXEC sp_executesql @query
    
    
    --GET all [Quarter] column, to add in ISNULL after PIVOT column -> e.g:  ISNULL([Q1], 0) AS [Q1], ISNULL([Q2], 0) AS [Q2]...
    DECLARE @col_name AS NVARCHAR(MAX)
    ;WITH distinct_col AS
    (
        SELECT DISTINCT [Quarter]
        FROM PivotSample
    )
    SELECT @col_name =
            STUFF(
            (
                SELECT ', ISNULL(' + QUOTENAME([Quarter]) + ', 0) AS ' + QUOTENAME([Quarter])
                FROM distinct_col
                ORDER BY [Quarter]
                FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)')
            ,1 , 1, '')
    
    --Generate query_result, to get result from ##TEMP_TBL after add in ISNULL
    DECLARE @query_result AS NVARCHAR(MAX)
    SET @query_result = 
        N'SELECT [Name], ' + @col_name + ' ' +
        'FROM ##TEMP_TBL
        ORDER BY [Name]'
    
    --Execute query_result, final result shown
    EXEC sp_executesql @query_result