#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