Оператор Case с одним или несколькими значениями

#sql #sql-server #tsql

Вопрос:

У меня есть следующая матрица, состоящая из нескольких переменных

 | A | B | C |
-------------
| X | X |   |
| X |   |   |
|   | X | X |
|   | X |   |
-------------
 

Я пытаюсь написать выражение case, которое выбирает отдельные столбцы, но также определяет, когда один или несколько столбцов заполняются другим значением

Пример

 case 
   when ColA = 'X' and ColB IS NULL and ColC IS NULL then 'Good'
   when ColA IS NULL and ColB = 'X' and ColC IS NULL then 'Bad'
   etc
end 
   
 

Но что мне писать в SQL,если я хочу проверить наличие двух или более столбцов (A,B или C), имеющих X, а остальные поля равны нулю? Это было бы для любой комбинации из 2 или более столбцов, имеющих X, без указания всех возможных комбинаций в операторе case (мои фактические данные содержат 8 столбцов с 2 или более возможными значениями в них). Не уверен, является ли это вложенным выражением случая или чем-то более иностранным, что ближе к циклу If/Then.

Комментарии:

1. Покажите нам некоторые примеры данных таблицы и ожидаемый результат. (Кроме того, это выражения в регистре.)

2. К вашему сведению case , это выражение , а не утверждение .

3. Это может быть редким случаем для оправдания определяемой пользователем функции

4. Является ли значение «X» значительным или это просто случай нулевого или ненулевого значения?

5. Вы пробовали с помощью COALESCE ()

Ответ №1:

Одним из методов может быть объединение строк, а затем сравнение результатов:

 select t.*,
       (case when len(concat(a, b, c, d, e, f, g, h)) like '%X%X%'
             then 'good' else 'bad'
        end) as two_x_flag
from t;
 

concat() Функция удобно игнорирует NULL значения.

Вы также можете использовать apply агрегацию для подсчета числа 'X' s:

 select t.*,
       (case when v.num_x >= 2 then 1 else 0 end) as two_x_flag
from t cross apply
     (select count(*) as num_x
      from (values (t.a), (t.b), (t.c), (t.d), (t.e), (t.f), (t.g), (t.h)) v(x)
      where v.x = 'X'
     ) v
 

Ответ №2:

Если я вас правильно понимаю, вы могли бы использовать apply() и iif для подсчета количества нулей или ненулей

 select t.* 
from t
outer apply (
    select Iif(a is null,0,1)   Iif(b is null,0,1)   Iif(c is null,0,1) t
)tot
where tot.t >= 2; /* eg only rows with at least 2 columns with X */
 

Другим еще более простым вариантом было бы использование concat , исключающее значения NULL

 select t.* 
from t
outer apply ( select Len(Concat(a,b,c))t )tot
where t >= 2
 

Ответ №3:

Проблема решена здесь с помощью приведенного ниже примера

 select 
count(case when c1 = '



then 1 else null end)
count(case when c2 = '

then 1 else null end)
count(case when c3 = '

then 1 else null end)
count(case when c4 = '

then 1 else null end)
count(case when c5 = '

then 1 else null end) cnt
from your_table