Попытка выбрать строки и включить первые 2 отличных ненулевых значения из 4 столбцов - PullRequest
1 голос
/ 07 марта 2012

У меня есть таблица, которая выглядит так:

CREATE TABLE [Test].[dbo].[MyTest]
(
[Id]    INT NOT NULL,
[ColA]  VARCHAR(255) NULL,
[ColB]  VARCHAR(255) NULL,
[ColC]  VARCHAR(255) NULL,
[ColD]  VARCHAR(255) NULL
);

И скажем, у меня есть:

Id     ColA     ColB     ColC     ColD
---------------------------------------
1       A        B        NULL     C
2       A        A        NULL     D
3       NULL     A        B        NULL
4       B        B        B        B
5       NULL     NULL     NULL     NULL

То, что я пытаюсь сделать, - это выбрать каждую строку из этой таблицы, но хочу только первые 2 отличных ненулевых значения из ColA-ColD по порядку. Другими словами, если для одной строки ColA и ColB не равны NULL и отличаются друг от друга, это те 2, которые я хочу для этой строки. Используя данные, которые я дал выше, желаемые результаты этого запроса будут:

1, A (from ColA), B (from ColB)
2, A (from ColA), D (from ColD)
3, A (from ColB), B (from ColC)
4, B (from ColA)

Обратите внимание, что если все данные для ColA-D для строки равны NULL, эта строка не выбирается. Также это нормально, если есть только 1 отличный от нуля столбец (вы можете видеть из строки результатов с Id 4) - это не должно быть 2, но в идеале это будет 2.

В принципе, я бы идеально мог получить TOP (2) DISTINCT от ColA-ColD, ГДЕ ни один из них не является NULL, но я понимаю, что TOP и DISTINCT работают со строками, а не со столбцами, как я пытаюсь это сделать. Любая помощь с благодарностью.

Спасибо!

Ответы [ 3 ]

2 голосов
/ 07 марта 2012

Это может быть быстрее всего с использованием CTE и оператора CASE:

;WITH cte AS (
    SELECT id
          ,COALESCE(ColA, ColB, ColC, ColD) AS col1
          ,ColB
          ,ColC
          ,ColD
    FROM   tbl
    )
SELECT id
      ,col1
      ,CASE WHEN ColB <> col1 THEN ColB 
            WHEN ColC <> col1 THEN ColC
            WHEN ColD <> col1 THEN ColD
            ELSE                   NULL
       END AS col2
--    ,COALESCE(NULLIF(ColB, col1)
--             ,NULLIF(ColC, col1)
--             ,NULLIF(ColD, col1)) As col2   -- alt. syntax doing the same
FROM   cte
WHERE  col1 IS NOT NULL
ORDER  BY id

Первый возвращенный столбец (col1) - это первый ненулевой столбец и второй столбец (col2)) является вторым отличным ненулевым значением в этом порядке.Оператор CASE работает, потому что NULL <> value никогда не оценивается как TRUE.

Если есть только одно отдельное значение, col2 возвращает NULL.
Если все исходные столбцы равны NULL, col1 равно NULL, и строка фильтруется предложением WHERE.

Комментируемый альтернативный синтаксис с NULLIF() короче, но я не ожидаю, что он будет быстрее.

0 голосов
/ 07 марта 2012

Попробуйте:

select id,
       coalesce(ColA, ColB, ColC, ColD) Result1,
       coalesce(nullif(coalesce(ColB, ColC, ColD), coalesce(ColA, ColB, ColC, ColD)),
                nullif(coalesce(ColC, ColD), coalesce(ColB, ColC, ColD)),
                nullif(ColD, coalesce(ColC, ColD)) ) Result2
from [Test].[dbo].[MyTest]
0 голосов
/ 07 марта 2012

Похоже, ваш дизайн базы данных не так.

Возможно, у вас не должно быть ColA,..,ColD столбцов.Похоже, у вас должна быть вторая таблица с id, type (A, .., D) и value.

С этой структурой вы можете легко прийтис любым выходом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...