2010-09-16 4 views
2

У меня есть большой, грязный отчет для записи, который объединяется через 5 таблиц. В одной таблице используется один столбец, который используется для нескольких разных значений - по существу столбца «тег», где теги используются творчески, в зависимости от того, какие разные метаданные пользователи хотят использовать.Устранение NULL при использовании CASE в SQL Server SELECT statement

В результате мой запрос для отчета возвращает 3 почти одинаковых строки, которые отличаются только столбцом «тег»; например, я мог бы получить:

NAME TAG EMAIL 
BOB A [email protected] 
BOB B [email protected] 
BOB C [email protected] 

То, что я хотел бы сделать, это разделить содержимое столбца TAG для возвращения в виде 3-х отдельных столбцов из запроса, как это:

NAME A B C EMAIL 
BOB A B C [email protected] 

Поэтому я попытался использовать функциональность SQL SERVER CASE/WHEN для этого; Я говорю, например, когда значение столбца Tag является «A», верните его в столбце «A»; если это «B», положите его в «B»; и т. д. Я думал, что это вернет вышеизложенное, но вместо этого оно дает мне следующее:

NAME A B C EMAIL 
BOB A NULL NULL [email protected] 
BOB NULL B NULL [email protected] 
BOB NULL NULL C [email protected] 

Это явно не идеальное.

Любые мысли, гении переполнения стека?

ответ

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 

EDIT: объяснить ...
В любое время вы используете Group By, вы говорите процессору запросов, что хотите, чтобы он агрегировал результаты в «ведра», где каждый ведро определяется уникальными значениями в столбцах [или выражениях] def ined в предложении Group By. Это означает, что окончательный набор результатов будет иметь одну и только одну строку для каждого уникального набора значений в этих столбцах [или выражениях], определенных в группе By. Все остальные столбцы или выражения, используемые в запросе (кроме тех, которые определены в группе 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' и т. д.

В вашей проблеме группа By используется просто для ограничения вывода, установленного в одну строку для каждого пользователя и электронной почты. Когда это будет сделано, будет только одна строка. Другие столбцы в операторе Select должны иметь Min(), [Max()), только для того, чтобы удовлетворить синтаксическое требование, упомянутое в полужирным курсивом выше ..В вашем случае в наборе будет только одна ненулевая строка, поэтому принимать Min() или Max() необходимо только из-за требования синтаксиса ...

+0

Думаю, я понимаю, почему это помогает, но можете ли вы это объяснить? Я извиняюсь за свое вопиющее невежество. – SuperNES

+0

Отредактированный ответ, чтобы добавить объяснения .. –

6

Данные должны быть получены pivot.

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

И результат выполнения выше запроса заключается в следующем:

NAME EMAIL   A B C 
----------------------------- 
BOB  [email protected] A B C