我正在制作一个存储过程,该过程将创建目标数据表(#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
答案 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;
如果您愿意,这也使添加更多级别变得非常容易。
注意:您可以将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;
答案 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