在SQL Server SELECT语句中使用CASE时消除NULL

时间:2010-09-16 19:32:59

标签: sql sql-server null case

我有一个大而乱的报告要写入连接5个表。一个表中有一列用于多个不同的值 - 实际上是一个“标记”列,其中标记以创造性的方式使用,具体取决于用户想要使用的各种元数据。

因此,我对报告的查询返回3个几乎相同的行,这些行仅在“tag”列中有所不同;例如,我可能会得到:

NAME TAG EMAIL  
BOB  A   BOB@EXAMPLE.COM  
BOB  B   BOB@EXAMPLE.COM  
BOB  C   BOB@EXAMPLE.COM  

我想要做的是将TAG列的内容拆分为3个单独的查询列,如下所示:

NAME A B C EMAIL
BOB  A B C BOB@EXAMPLE.COM

所以我尝试使用SQL SERVER CASE / WHEN功能来执行此操作;我说,例如,当Tag列的值为“A”时,将其返回到“A”列;如果它是“B”,则把它放在“B”中;我认为这会返回上面的内容,但它却给了我这个:

NAME A    B    C    EMAIL
BOB  A    NULL NULL BOB@EXAMPLE.COM
BOB  NULL B    NULL BOB@EXAMPLE.COM
BOB  NULL NULL C    BOB@EXAMPLE.COM

这显然不太理想。

任何想法,Stack Overflow的天才?

2 个答案:

答案 0 :(得分:6)

您需要pivot数据。

;with Report (name, tag, email) as
(
select 'BOB', 'A', 'BOB@BOB.COM' union
select 'BOB', 'B', 'BOB@BOB.COM' union
select 'BOB', 'C', 'BOB@BOB.COM' 
)
select * from Report
pivot 
( min(tag) for  tag in ([A], [B], [C]))  
as pvt

运行上述查询的结果如下:

NAME    EMAIL         A  B  C
-----------------------------
BOB     BOB@BOB.COM   A  B  C

答案 1 :(得分:5)

试试这个:

   Select Name,
    Min (Case When tag = 'A' Then Tag End) A,
    Min (Case When tag = 'B' Then Tag End) B,
    Min (Case When tag = 'C' Then Tag End) C,
    email
   From tableName
   Group By Name, email

编辑:解释...
无论何时使用Group By,您都要告诉查询处理器您希望它将结果聚合到“桶”中,其中每个桶都由Group By子句中定义的列[或表达式]中的唯一值定义。这意味着最终结果集将为Group By中定义的那些列[或表达式]中的每个唯一值集合只有一行。查询中使用的所有其他列或表达式(除了在分组中定义的那些), 必须是基于聚合函数的表达式 (如Count(), Sum(),Avg(),Min(),Max()等等),它们根据计算产生一个值,该计算将应用于预聚合结果集中的所有行。例如,如果我要Group By姓氏的第一个字符:

Select Left(LastName, 1), Count(*), 
   Sum(Salaray, Avg(Height), 
   Min(DateOfBirth), etc.
  From Table
  Group By Left(LastName, 1)

然后我将在输出中最多获得26行(字母表中每个字母一行),输出中的所有其他列必须基于某些聚合函数,以应用于原始集合中的所有行。姓氏以'A'开头,然后姓氏以qa'B'开头的所有行等等。

在您的问题中,Group By仅用于将输出设置限制为每个不同用户和电子邮件一行。完成此操作后,每个只有一行.Select语句中的其他列需要Min(),[Max()也能正常工作),只是为了满足语法要求在上面的 粗体斜体 中提到..在你的情况下,集合中只会有一个非空行,所以取Min()或者Max()是必要的只是因为语法要求......