【问题标题】:Pivot function returns only grand totalPivot 函数仅返回总计
【发布时间】:2020-12-16 11:02:54
【问题描述】:

我正在尝试了解数据透视表的工作原理。

IF OBJECT_ID(N'tempdb..#exams') IS NOT NULL
BEGIN
DROP TABLE #exams
END
GO

create table #exams (
id uniqueidentifier,
exam nvarchar(max),
technician nvarchar(max)
)

insert into #exams 
values 
(newid(),'Esame1','Tecnico1'),
(newid(),'Esame2','Tecnico1'),
(newid(),'Esame1','Tecnico2'),
(newid(),'Esame3','Tecnico1'),
(newid(),'Esame3','Tecnico2'),
(newid(),'Esame3','Tecnico3'),
(newid(),'Esame3','Tecnico1')

我知道如何使用 sum case 来获得我想要的东西:

select
 exam,
 sum(case when technician = 'Tecnico1' then 1 else 0 end) as Tecnico1,
 sum(case when technician = 'Tecnico2' then 1 else 0 end) as Tecnico2,
 sum(case when technician = 'Tecnico3' then 1 else 0 end) as Tecnico3
 from #exams
 group by exam
 order by exam
exam    Tecnico1    Tecnico2    Tecnico3
Esame1    1            1            0
Esame2    1            0            0
Esame3    2            1            1

顺便说一句,我有很多技术人员,我想使用动态列自动执行我的查询。

当我尝试枢轴语法时

    select * from (
        select exam,
               technician 
               from #exams
        ) as t
        pivot 
        (   count(exam)
                for technician in (Tecnico1,Tecnico2,Tecnico3)
            ) as t

我只得到总计

Tecnico1    Tecnico2    Tecnico3
   4          2            1

我怎样才能得到与 sum case 语法相同的结果?

【问题讨论】:

    标签: sql sql-server pivot dynamic-pivot


    【解决方案1】:

    您必须在子查询中包含 id:

      select * from (
        select id,exam,
               technician 
               from #exams
        ) as t
        pivot 
        (   count(id)
                for technician in (Tecnico1,Tecnico2,Tecnico3)
            ) as t
    

    动态:

    DECLARE @sql  nvarchar(max);
    DECLARE @columnname nvarchar(max);
    
    
    SELECT @columnname=COALESCE(@columnname+ ',', '') + QUOTENAME(CAST(q.technician AS nvarchar(20)),'[]')
    FROM
    (SELECT DISTINCT e.technician
    FROM #exams e) AS q
     
    
     SET @sql=
    'select * from (
      select id,exam,
             technician 
             from #exams
      ) as t
      pivot 
      (   count(id)
              for technician in ('+@columnname+')
          ) as t'
    
    EXECUTE sp_executesql @sql
    

    【讨论】:

    • 非常感谢。我已经在我的真实案例中完成了动态部分,但我被你用 id 字段解决的问题所困扰。最好的问候。
    【解决方案2】:

    pivot 语法不支持将值列表作为子查询传递。这是 SQL 中的一个典型限制:查询必须返回一组固定列。

    您要求的内容需要动态 SQL。在 SQL Server 中,这看起来像:

    declare @sql  as nvarchar(max);
    
    select @sql = 
        'select exam, ' 
        + string_agg(
        'sum(case when technician = ''' + technician + ''' then 1 else 0 end) as [' + technician + ']',
        ', '
        )
        + ' from #exams group by exam'
    from #exams;
        
    execute(@sql);
    

    【讨论】:

    • 可能希望确保您正确引用/转义 technician 的值。我怀疑它更可能是一个名字,它们很容易包含单引号 (')。考虑到 OP 声明该值可能包含多达 10 亿个字符,我建议确实应该正确引用它。
    猜你喜欢
    • 2020-11-28
    • 1970-01-01
    • 2012-06-20
    • 1970-01-01
    • 1970-01-01
    • 2018-05-11
    • 2018-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多