Замена NULL из результатов запроса CASE

У меня есть следующий код, который генерирует данные, подобные моим. Сообщение здесь (PivotWithoutAggregateFunction) предполагает, что использование оператора CASE, а не PIVOT, лучше для нечисловые значения. Что, если это не так, я думаю, сейчас самое время это исправить!

      DECLARE @QA1 TABLE (SID varchar(7), FormID varchar(max), DateExam date, Present varchar(3))
      INSERT INTO @QA1 VALUES(1, 'Form1', '20110101', 'Yes')
      INSERT INTO @QA1 VALUES(2, 'Form1', '20110201', 'Yes')
      INSERT INTO @QA1 VALUES(3, 'Form1', '20110301', 'Yes')
      INSERT INTO @QA1 VALUES(4, 'Form1', '20110401', 'Yes')
      INSERT INTO @QA1 VALUES(5, 'Form1', '20110122', 'Yes')
      INSERT INTO @QA1 VALUES(1, 'Form2', '20110222', 'Yes')
      INSERT INTO @QA1 VALUES(2, 'Form2', '20110322', 'Yes')
      INSERT INTO @QA1 VALUES(3, 'Form2', '20110422', 'Yes')
      INSERT INTO @QA1 VALUES(1, 'Form3', '20110128', 'Yes')
      INSERT INTO @QA1 VALUES(1, 'Form4', '20110228', 'Yes')
      INSERT INTO @QA1 VALUES(5, 'Form5', '20110328', 'Yes')
      INSERT INTO @QA1 VALUES(5, 'Form6', '20111228', 'Yes')
      INSERT INTO @QA1 VALUES(4, 'Form2', '20111228', 'Yes')

    SELECT SID,
    MIN(CASE FormID WHEN 'Form1' THEN Present END) AS 'First',
    MIN(CASE FormID WHEN 'Form2' THEN Present END) AS 'Second',
    MIN(CASE FormID WHEN 'Form3' THEN Present END) AS 'Third',
    MIN(CASE FormID WHEN 'Form4' THEN Present END) AS 'Fourth',
    MIN(CASE FormID WHEN 'Form5' THEN Present END) AS 'Fifth',
    MIN(CASE FormID WHEN 'Form6' THEN Present END) AS 'Sixth'

    FROM @QA1

    GROUP BY SID
    ORDER BY SID

Однако на выходе есть NULL в строке/столбцах, которые не имеют никаких форм, которые, хотя и являются правильными, мне гораздо труднее читать.

      SID    First  Second   Third  Fourth   Fifth   Sixth
       1      Yes    Yes      Yes     Yes     NULL    NULL
       2      Yes    Yes      NULL    NULL    NULL    NULL
       3      Yes    Yes      NULL    NULL    NULL    NULL
       4      Yes    Yes      NULL    NULL    NULL    NULL
       5      Yes    NULL     NULL    NULL    Yes     Yes

Как я могу изменить свой CASE, чтобы я либо ничего не получил (т.е. ''), либо хотя бы "Нет"?


person user918967    schedule 05.09.2011    source источник


Ответы (3)


Это идеальный запрос для оператора PIVOT.

SELECT
  SID,
  COALESCE([Form1],'No') AS [First],
  COALESCE([Form2],'No') AS [Second],
  COALESCE([Form3],'No') AS [Third],
  COALESCE([Form4],'No') AS [Fourth],
  COALESCE([Form5],'No') AS [Fifth],
  COALESCE([Form6],'No') AS [Sixth]
FROM (
  SELECT SID, FormID, Present FROM @QA1
) S
PIVOT (
  MIN(Present)
  FOR FormID IN ([Form1],[Form2],[Form3],[Form4],[Form5],[Form6])
) AS P
ORDER BY SID;
person Steve Kass    schedule 05.09.2011

Вы должны иметь возможность обернуть COALESCE вокруг оскорбительных MIN, например:

COALESCE(MIN(CASE FormID WHEN 'Form1' THEN Present END), 'No') AS 'First',

Я не уверен, насколько это устроит SQL Server, но это довольно стандартный SQL.

Применить корректировку NULL после MIN, вероятно, лучше, чем пытаться выбрать безопасное значение для помещения в MIN.

person mu is too short    schedule 05.09.2011
comment
Это сделало это! Спасибо, я не знал, COALESCE - person user918967; 05.09.2011
comment
@ user918967: Каждый должен знать о COALESCE, это замечательная и полезная функция с переменным числом аргументов (т. е. вы можете вызывать ее с любым количеством аргументов). Вы можете использовать '', если вам не нравится 'No'. - person mu is too short; 05.09.2011

person    schedule
comment
Когда я использую этот синтаксис в поле DateExam, если форма отсутствует, дата переходит на 1900-01-01. Могу ли я изменить это на ''? - person user918967; 05.09.2011
comment
@ user918967 Вы можете, но тогда вам нужно преобразовать поле DateExam в varchar, иначе я не думаю, что SQL это понравится; другими словами, это: isnull(CONVERT(varchar(10),DateExam,101),'') - person Icarus; 05.09.2011
comment
Спасибо еще раз ! Последний бит. Я добавил 34 дня к DateExam и назвал его DateThirtyFuture, чтобы я мог видеть, просрочена ли моя форма. Итак, что я хотел бы сделать, это когда форма присутствует, оставьте «Да» в поле, но если оно пустое, проверьте, не прошло ли оно более 34 дней (DateThirtyFuture), и если да, поставьте «Over Due», если нет, оставьте поле пустым? - person user918967; 05.09.2011