SQL初学者问题:多列为CASE AS END?

时间:2018-09-23 14:06:05

标签: sql db2

我正在制作一个存储过程,该过程将创建目标数据表(#tmp_target_table),对其进行一些检查,然后将结果输出到结果集表(#tmp_resultset_table)中。除了来自#tmp_target_table的现有列之外,结果集表还需要具有多个新列:user_warning_id,user_warning_note和user_warning_detail。

我有一个工作正常的存储过程,如下所示,但这存在一些问题。我需要重复编写conditionA,conditionB和conditionB,但将来需要更改这些条件。您将如何编写更具扩展性的代码?

<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 :(得分:1)

在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;

如果您愿意,这也使添加更多级别变得非常容易。

注意:您可以将vv2合并到一个值列表中。我将它们分开了,因为您可能要考虑将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;

答案 1 :(得分:0)

您可以将消息放入表中,并将条件逻辑放入函数中。
仅使用临时表,以便您可以对其进行测试。

警告

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'

必须满足某些表中条件的数据值... #conditions

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

答案 2 :(得分:0)

可能是最简单的方法,它是将“条件”移到子选择中,然后在另一个选择中引用标记。例如

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
    )

尽管Gordon的回答也很简洁,即使它在访问计划中添加了两个联接。在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