【问题标题】:SQL Pivot Query with aggregation & Total具有聚合和总计的 SQL 透视查询
【发布时间】:2021-06-29 19:22:41
【问题描述】:

表-A

ProductId BrandName
1 Brand-1
2 Brand-2
3 Brand-3

表-B

DCDate DCNo ProductId Weight
2021-03-09 3 1 12.5
2021-03-09 3 1 12.6
2021-03-09 3 1 12.5
2021-03-09 3 2 10.5
2021-03-09 3 2 10.4
2021-03-09 3 3 15.5
2021-03-09 1 1 12.5
2021-03-09 1 3 15.7
2021-03-09 2 2 10.6
2021-03-09 4 1 12.7
2021-03-09 4 1 12.6

预期结果:-

BrandName 1 2 3 4
Brand-1 1 0 3 2
Brand-2 0 1 2 0
Brand-3 1 0 1 0

需要动态透视查询

我尝试了什么

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME([DCNo]) from [Table-B] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')

set @query = 'SELECT ' + @cols + '
             from 
             (
                SELECT a.[DCNo] , b.[BrandName], count(*) as Total FROM [Table-B] a inner join [Table-A] b on a.[ProductID]=b.[ProductID] group by [DCNo] , b.[BrandName] order by DCNo, b.[BrandName]
            ) x
            pivot 
            (
                max(Total)
                for DCNo in (' + @cols + ')
            ) p '

execute(@query)

【问题讨论】:

    标签: sql dynamic pivot


    【解决方案1】:

    我在 sqlfiddle 中重新创建了它:http://sqlfiddle.com/#!18/d1554/9。 你很接近,但我有时发现将所有总和/计数/分组逻辑移到查询的 PIVOT 部分更容易。产生更简单的查询(大多数时候)

    CREATE TABLE [Table-A] (
      ProductId INT,
      BrandName VARCHAR(50)
    )
    
    CREATE TABLE [Table-B](
      DCDate DATETIME,
      DCNo INT,
      ProductId INT,
      Weight DECIMAL
    )
    
    INSERT INTO [Table-A] VALUES
    (1, 'CAT'),
    (2, 'APPLE'),
    (3, 'PARROT')
    
    INSERT INTO [Table-B] VALUES
    ('2021-03-09', 3,   1,  12.5),
    ('2021-03-09', 3,   1,  12.6),
    ('2021-03-09', 3,   1,  12.5),
    ('2021-03-09', 3,   2,  10.5),
    ('2021-03-09', 3,   2,  10.4),
    ('2021-03-09', 3,   3,  15.5),
    ('2021-03-09', 1,   1,  12.5),
    ('2021-03-09', 1,   3,  15.7),
    ('2021-03-09', 2,   2,  10.6),
    ('2021-03-09', 4,   1,  12.7),
    ('2021-03-09', 4,   1,  12.6)
    
    -- Query
    DECLARE @cols AS NVARCHAR(MAX) = '';
    DECLARE @nullcols AS NVARCHAR(MAX) = '';
    DECLARE @query  AS NVARCHAR(MAX);
    
    -- Determine columns
    ;WITH cte AS (
      SELECT 
        DISTINCT 
        dcno,
        ',' + QUOTENAME([DCNo]) AS col,
        ', ISNULL(' + QUOTENAME([DCNo]) + ', 0) AS ' + QUOTENAME([DCNo]) AS nullcol
      FROM [Table-B]
    )
    SELECT
      @cols += col,
      @nullcols += nullcol
    FROM cte
    ORDER BY dcno
    SET @cols = SUBSTRING(@cols, 2, LEN(@cols)) 
    
    -- create query
    SET @query = N';with CTE AS 
    (
      SELECT 
        a.BrandName, 
        a.ProductId,
        b.DCNo, 
        1 as Value
      FROM [Table-A] a
      INNER JOIN [Table-B] b
         ON a.ProductId = b.ProductId
    )
    SELECT BrandName ' + @nullcols + ' FROM 
    (SELECT * FROM cte) p
    PIVOT
    (
      SUM(Value)
      FOR DCNo IN (' + @cols + ')    
    ) AS pvt
    ORDER BY pvt.ProductId
    '
    -- SELECT @query
    execute(@query)
    

    【讨论】:

    • 我需要按产品 ID 和 DCNO 编号排序
    • ProductId 现在是一个聚合值,'in order by Product Id' 是什么意思?您希望 DCNO 按什么顺序排列?
    • 检查此sqlfiddle.com/#!18/d1554/1 现在订单基于品牌名称,如 APPLE、CAT、PARROT,我需要按 ProductId 为 CAT、APPLE、PARROT 订单
    • DCNO 显示为 1, 10,100,2,20,200,我需要这个为 1,2,10,20,100,200
    • 我将答案更改为对 dcno 进行数字排序并按 productId 排序
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    相关资源
    最近更新 更多