【问题标题】:SQL Server 2012 PIVOT without aggregate没有聚合的 SQL Server 2012 PIVOT
【发布时间】:2013-03-24 07:36:49
【问题描述】:

我有以下示例数据:

Id    Name     Category
-----------------------
1     Joe       A
2     Joe       B
3     Joe       D
4     Mary      A
5     Mary      C
6     Mary      D

我想显示一个人所属的类别,如下所示:

Name   CategoryA  CategoryB  CategoryC  CategoryD
--------------------------------------------------
Joe       X          X                     X
Mary      X                     X          X

1 和 0 可以用来代替 X 和空白。

对我来说,这听起来像是一个 PIVOT 问题。

【问题讨论】:

标签: sql-server tsql pivot sql-server-2012


【解决方案1】:

您可以通过多种方式转换数据。有些使用聚合函数,有些则不使用。但即使您正在旋转字符串,您仍然可以应用聚合。

与 CASE 聚合:

select name,
  max(case when category = 'A' then 'X' else '' end) CategoryA,
  max(case when category = 'B' then 'X' else '' end) CategoryB,
  max(case when category = 'C' then 'X' else '' end) CategoryC,
  max(case when category = 'D' then 'X' else '' end) CategoryD
from yourtable 
group by name

SQL Fiddle with Demo

静态枢轴:

即使值是字符串,您仍然可以使用PIVOT 函数来转换数据。如果您有已知数量的类别,则可以对查询进行硬编码:

select name, 
  coalesce(A, '') CategoryA, 
  coalesce(B, '') CategoryB, 
  coalesce(C, '') CategoryC, 
  coalesce(C, '') CategoryD
from
(
  select name, category, 'X' flag
  from yourtable
) d
pivot
(
  max(flag)
  for category in (A, B, C, D)
) piv

SQL Fiddle with Demo

动态枢轴:

如果您有未知数量的类别,那么您可以使用动态 SQL:

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

select @cols = STUFF((SELECT  ',' + QUOTENAME(category) 
                    from yourtable
                    group by category
                    order by category
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsNull = STUFF((SELECT  ', coalesce(' + QUOTENAME(category)+', '''') as '+QUOTENAME('Category'+category)
                    from yourtable
                    group by category
                    order by category
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT name, ' + @colsNull + ' 
              from 
             (
                select name, category, ''X'' flag
                from yourtable
            ) x
            pivot 
            (
                max(flag)
                for category in (' + @cols + ')
            ) p '

execute(@query)

SQL Fiddle with Demo

多重连接:

select c1.name,
  case when c1.category is not null then 'X' else '' end as CategoryA,
  case when c2.category is not null then 'X' else '' end as CategoryB,
  case when c3.category is not null then 'X' else '' end as CategoryC,
  case when c4.category is not null then 'X' else '' end as CategoryD
from yourtable c1
left join yourtable c2
  on c1.name = c2.name
  and c2.category = 'B'
left join yourtable c3
  on c1.name = c3.name
  and c3.category = 'C'
left join yourtable c4
  on c1.name = c4.name
  and c4.category = 'D'
where c1.category = 'A'

SQL Fiddle with Demo

所有查询都会给出结果:

| NAME | CATEGORYA | CATEGORYB | CATEGORYC | CATEGORYD |
--------------------------------------------------------
|  Joe |         X |         X |           |         X |
| Mary |         X |           |         X |         X |

【讨论】:

  • 嘿...我一直在看着答案得到编辑/完善。感谢您编辑答案以包括我对结果包含 X/空白的要求。这符合接受的答案。
  • @BlakeB。是的,这叫做没有完全阅读问题,对此感到抱歉。 :)
  • 事实证明,该解决方案的“聚合与 CASE”版本的性能比 PIVOT 解决方案好得多。
  • @BlakeB。这就是为什么我提供了多个版本的解决方案。然后,您可以决定哪种方式更适合您。
猜你喜欢
  • 2019-07-03
  • 2012-02-20
  • 1970-01-01
  • 2016-10-16
  • 2014-12-30
  • 1970-01-01
  • 2010-11-17
  • 2020-06-22
  • 2018-12-11
相关资源
最近更新 更多