Вопрос SQL для начинающих: CASE AS END для нескольких столбцов? - PullRequest
0 голосов
/ 23 сентября 2018

Я делаю хранимую процедуру, которая создает целевую таблицу данных (#tmp_target_table), выполняет некоторые проверки и выводит результаты в таблицу результатов (#tmp_resultset_table).Таблица результирующих наборов должна иметь несколько новых столбцов: user_warning_id, user_warning_note и user_warning_detail в дополнение к существующим столбцам из #tmp_target_table.

У меня есть рабочая хранимая процедура, как показано ниже, но это имеет некоторые проблемы.Мне нужно писать условие A, условие B и условие B несколько раз, но эти условия необходимо будет изменить в будущем.Как бы вы написали более расширяемый код?

<Working code>
SELECT existing_col1, existing_col2,    
CASE 
WHEN conditionA 
 THEN user_warning_id_A 
WHEN conditionB
  THEN user_warning_id_B
WHEN conditionC
  THEN user_warning_id_C
END AS user_warning_id,       
CASE 
WHEN conditionA 
  THEN user_warning_note_A 
WHEN conditionB
  THEN user_warning_note_B
WHEN conditionC
  THEN user_warning_note_C
END AS user_warning_note,       
CASE 
WHEN conditionA 
  THEN user_warning_detail_A 
WHEN conditionB
  THEN user_warning_detail_B
WHEN conditionC
  THEN user_warning_detail_C
END AS user_warning_detail, 
existing_col3, existing_col4      
INTO #tmp_resultset_table     
FROM #tmp_target_table 

SELECT * FROM #tmp_resultant_table

Ответы [ 3 ]

0 голосов
/ 24 сентября 2018

Вы можете поместить сообщения в таблицу и логику условий в функцию.
Просто используя временные таблицы, чтобы вы могли проверить их.

Предупреждения

select warningID = 1, note = 'note 1', detail = 'notes on warning 1'
into #warning
union
select warningID = 2, note = 'note 2', detail = 'notes on warning 2'
union
select warningID = 3, note = 'note 3', detail = 'notes on warning 3'
union
select warningID = 4, note = 'note 4', detail = 'notes on warning 4'

Значения данных, которые должны соответствовать условиям из некоторой таблицы ... # условия

select condID = 1, val1 = 10, val2 = 1
into #conditions
union
select condID = 2, val1 = 20, val2 = 1
union
select condID = 3, val1 = 5, val2 = 2
union
select condID = 4, val1 = 30, val2 = 1
union
select condID = 4, val1 = 12, val2 = 1

Затем функция, которая определяет предупреждения на основе условийв данных.Принимает значения в качестве входных данных и возвращает предупреждениеID

create function testWarningF
(
      @val1In int
)
returns int
as
begin
declare @retVal int

select @retVal = case when @val1In <= 10 then 1
            when @val1In > 10 and @val1In <=20 then 2
            else 3
        end
return @retVal
end
go

Затем SQL ...

select *
from #conditions c
inner join #warning w on w.warningID = dbo.warningF(val1)

... возвращает этот результат

condID  val1    val2    warningID   note    detail
1       10      1       1          note 1   notes on warning 1
2       20      1       2          note 2   notes on warning 2
3       5       2       1          note 1   notes on warning 1
4       12      1       2          note 2   notes on warning 2
4       30      1       3          note 3   notes on warning 3
0 голосов
/ 24 сентября 2018

Возможно, самый простой способ - переместить Условия в подвыбор, а затем сослаться на токен в другом.Например,

SELECT  existing_col1
,       existing_col2    
,       CASE CON 
             WHEN 'A' THEN user_warning_id_A 
             WHEN 'B' THEN user_warning_id_B
             WHEN 'C' THEN user_warning_id_C     END AS user_warning_id       
,       CASE CON
             WHEN 'A' THEN user_warning_note_A 
             WHEN 'B' THEN user_warning_note_B
             WHEN 'C' THEN user_warning_note_C   END AS user_warning_note       
,       CASE CON
             WHEN 'A' THEN user_warning_detail_A 
             WHEN 'B' THEN user_warning_detail_B
             WHEN 'C' THEN user_warning_detail_C END AS user_warning_detail 
,       existing_col3
,       existing_col4        
FROM (
        SELECT  T.*
        ,       CASE WHEN conditionA THEN 'A' 
                     WHEN conditionB THEN 'B'
                     WHEN conditionC THEN 'C'     END AS CON       
        FROM
            #tmp_target_table T
    )

, хотя ответ Гордона также точен, хотя он добавляет два соединения в план доступа.В синтаксисе Db2 это работает (в любом случае на Db2 11.1.3.3)

select tt.*,
       v2.user_warning_id, v2.user_warning_note, v2.user_warning_detail
from #tmp_target_table tt
,    (values (case when conditionA then 'a'
                   when conditionB then 'b'
                   when conditionC then 'c'
              end)
     ) v(cond) left join
     (values ('a', 'user_warning_id_A', 'user_warning_note_A', 'user_warning_detail_A'),
             ('b', 'user_warning_id_B', 'user_warning_note_B', 'user_warning_detail_B'),
             ('c', 'user_warning_id_C', 'user_warning_note_C', 'user_warning_detail_C')
     ) v2(cond, user_warning_id, user_warning_note, user_warning_detail)
     on v2.cond = v.cond;

тестирование с

create table #tmp_target_table(i int);
insert into #tmp_target_table(values 1);
create variable conditionA boolean;
create variable conditionB boolean default true;
create variable conditionC boolean;

возвращает

 I USER_WARNING_ID   USER_WARNING_NOTE   USER_WARNING_DETAIL
 - ----------------- ------------------- ---------------------
 1 user_warning_id_B user_warning_note_B user_warning_detail_B
0 голосов
/ 23 сентября 2018

В SQL Server вы можете использовать боковое соединение (т. Е. apply), чтобы упорядочить данные, чтобы вы могли использовать справочную таблицу:

select tt.*,
       v2.user_warning_id, v2.user_warning_note, v2.user_warning_detail
from #tmp_target_table tt cross apply
     (values (case when conditionA then 'a'
                   when conditionA then 'b'
                   when conditionA then 'c'
              end)
     ) v(cond) left join
     (values ('a', user_warning_id_A, user_warning_note_A, user_warning_detail_A),
             ('b', user_warning_id_B, user_warning_note_B, user_warning_detail_B),
             ('c', user_warning_id_C, user_warning_note_C, user_warning_detail_C)
     ) v2(cond, user_warning, user_warning_note, user_warning_detail)
     on v2.cond = v.cond;

Это также довольно легко добавляет дополнительныеуровни, если хотите.

Примечание. Вы можете объединить v и v2 в один список значений.Я разделил их, потому что вы, возможно, захотите сделать v2 фактической справочной таблицей.

РЕДАКТИРОВАТЬ:

DB2 поддерживает боковые объединения с ключевым словом lateral.Я не помню, поддерживает ли DB2 values().Итак, попробуйте это:

select tt.*,
       v2.user_warning_id, v2.user_warning_note, v2.user_warning_detail
from #tmp_target_table tt cross join lateral
     (select (case when conditionA then 'a'
                   when conditionA then 'b'
                   when conditionA then 'c'
              end)
      from sysibm.sysdummy1
     ) v(cond) left join
     (select 'a' as cond, user_warning_id_A as user_warning_id, user_warning_note_A as user_warning_note, user_warning_detail_A user_warning_detail
      from sysibm.sysdummy1
      union all
      select 'b', user_warning_id_B, user_warning_note_B, user_warning_detail_B
      from sysibm.sysdummy1
      union all
      select 'c', user_warning_id_C, user_warning_note_C, user_warning_detail_C
      from sysibm.sysdummy1
     ) v2(cond, user_warning, user_warning_note, user_warning_detail)
     on v2.cond = v.cond;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...