将 3 个案例陈述合并或简化为一个
Posted
技术标签:
【中文标题】将 3 个案例陈述合并或简化为一个【英文标题】:Merging or Simplifying 3 case statements to One 【发布时间】:2020-03-31 17:11:36 【问题描述】:我会将以下 3 个 case 语句合并为一个并尽可能简化。查询的目的是根据 3 列找出任何具有无效或有效电话号码的成员。如果任何列具有有效的电话号码,则它是有效的。如果全部无效,则视为无效。任何帮助都会很棒。
CASE
WHEN REGEXP_REPLACE(DAY_PH, '[^[:digit:]'''']', NULL) IS NULL
THEN 1
WHEN REGEXP_REPLACE(DAY_PH, '[^[:digit:]'''']', NULL) ='9999999999'
THEN 1
WHEN LENGTH(TRIM(REGEXP_REPLACE(DAY_PH, '[^[:digit:]'''']', NULL))) = 10
THEN 0
ELSE 1
END INVALID_DAY_PH,
CASE
WHEN REGEXP_REPLACE(EVE_PH, '[^[:digit:]'''']', NULL) IS NULL
THEN 1
WHEN REGEXP_REPLACE(EVE_PH, '[^[:digit:]'''']', NULL)='9999999999'
THEN 1
WHEN LENGTH(TRIM(REGEXP_REPLACE(EVE_PH, '[^[:digit:]'''']', NULL))) = 10
THEN 0
ELSE 1
END INVALID_EVE_PH,
CASE
WHEN REGEXP_REPLACE(MOB_PH, '[^[:digit:]'''']', NULL) IS NULL
THEN 1
WHEN REGEXP_REPLACE(MOB_PH, '[^[:digit:]'''']', NULL)='9999999999'
THEN 1
WHEN LENGTH(TRIM(REGEXP_REPLACE(MOB_PH, '[^[:digit:]'''']', NULL))) = 10
THEN 0
ELSE 1
END INVALID_MOB_PH,
【问题讨论】:
您能否逐字说明在哪些情况下电话号码无效? 当然,1)。如果 3 列为空白则无效.. 2). 如果 3 列全部为 999999999 - 10 位则无效..1 和 2 可以像 2 列有空白和第 3 列全部为 9 一样无效..跨度> 显示所有排列的示例数据和您想要的结果可能会使这更清楚一点。为什么你的正则表达式类中有单引号(两次);为什么 9999999999 是一个神奇的数字? 【参考方案1】:您可以通过将正则表达式调用推入内联视图或 CTE 来简化一点,这样您就不必重复它们:
select id, day_ph, eve_ph, mob_ph,
case when length(day_ph_cln) = 10 and day_ph_cln != '9999999999'
then 0 else 1 end as invalid_day_ph,
case when length(eve_ph_cln) = 10 and eve_ph_cln != '9999999999'
then 0 else 1 end as invalid_eve_ph,
case when length(mob_ph_cln) = 10 and mob_ph_cln != '9999999999'
then 0 else 1 end as invalid_mob_ph
from (
select id, day_ph, eve_ph, mob_ph,
regexp_replace(day_ph, '[^[:digit:]'''']') as day_ph_cln,
regexp_replace(eve_ph, '[^[:digit:]'''']') as eve_ph_cln,
regexp_replace(mob_ph, '[^[:digit:]'''']') as mob_ph_cln
from your_table
);
trim()
似乎没有做任何事情,所以我把它省略了 - 正则表达式已经删除了所有空格,因为它们不是数字(或单引号......我已经离开了模式完好无损,但不确定它是否有意义......)
如果您想要一个最终标志来显示是否所有其他标志都无效,那么您可以使用least()
,如果其他三个标志中的任何一个为零,它将给您零,否则为 1。
select id, day_ph, eve_ph, mob_ph,
case when length(day_ph_cln) = 10 and day_ph_cln != '9999999999'
then 0 else 1 end as invalid_day_ph,
case when length(eve_ph_cln) = 10 and eve_ph_cln != '9999999999'
then 0 else 1 end as invalid_eve_ph,
case when length(mob_ph_cln) = 10 and mob_ph_cln != '9999999999'
then 0 else 1 end as invalid_mob_ph,
least(
case when length(day_ph_cln) = 10 and day_ph_cln != '9999999999'
then 0 else 1 end,
case when length(eve_ph_cln) = 10 and eve_ph_cln != '9999999999'
then 0 else 1 end,
case when length(mob_ph_cln) = 10 and mob_ph_cln != '9999999999'
then 0 else 1 end
) as all_invalid
from (
select id, day_ph, eve_ph, mob_ph,
regexp_replace(day_ph, '[^[:digit:]'''']') as day_ph_cln,
regexp_replace(eve_ph, '[^[:digit:]'''']') as eve_ph_cln,
regexp_replace(mob_ph, '[^[:digit:]'''']') as mob_ph_cln
from your_table
);
或使用其他级别的子查询(或 CTE)来删除重复:
select id, day_ph, eve_ph, mob_ph,
invalid_day_ph, invalid_eve_ph, invalid_mob_ph,
least(invalid_day_ph, invalid_eve_ph, invalid_mob_ph) as all_invalid
from (
select id, day_ph, eve_ph, mob_ph,
case when length(day_ph_cln) = 10 and day_ph_cln != '9999999999'
then 0 else 1 end as invalid_day_ph,
case when length(eve_ph_cln) = 10 and eve_ph_cln != '9999999999'
then 0 else 1 end as invalid_eve_ph,
case when length(mob_ph_cln) = 10 and mob_ph_cln != '9999999999'
then 0 else 1 end as invalid_mob_ph
from (
select id, day_ph, eve_ph, mob_ph,
regexp_replace(day_ph, '[^[:digit:]'''']') as day_ph_cln,
regexp_replace(eve_ph, '[^[:digit:]'''']') as eve_ph_cln,
regexp_replace(mob_ph, '[^[:digit:]'''']') as mob_ph_cln
from your_table
)
);
如果您只想要最后一个标志,那么您可以组合大小写表达式:
select id, day_ph, eve_ph, mob_ph,
case when (length(day_ph_cln) = 10 and day_ph_cln != '9999999999')
or (length(eve_ph_cln) = 10 and eve_ph_cln != '9999999999')
or (length(mob_ph_cln) = 10 and mob_ph_cln != '9999999999')
then 0 else 1 end as all_invalid
from (
select id, day_ph, eve_ph, mob_ph,
regexp_replace(day_ph, '[^[:digit:]'''']') as day_ph_cln,
regexp_replace(eve_ph, '[^[:digit:]'''']') as eve_ph_cln,
regexp_replace(mob_ph, '[^[:digit:]'''']') as mob_ph_cln
from your_table
);
您没有提供任何样本数据来验证这是否提供了您想要的结果;但是here's a db<>fiddle 有一些非常基本的虚构数据。
【讨论】:
提供的答案和示例非常好,感谢您抽出宝贵时间,我不打算使用 CTE 或派生表。我想将所有 3 个电话号码合并为一个,这意味着我需要自定义列 - 基于 3 个电话号码的 Y/N。如果有效 Y,否则为 N。 使用 Y/N 代替 0/1 不是问题。 (对于某些示例,可能需要最大而不是最小)。我不确定您为什么不想使用 CTE/内联视图/派生表。这应该是结果集中的额外列,还是实际基表中的列?相同的逻辑可以用于虚拟列。以上是关于将 3 个案例陈述合并或简化为一个的主要内容,如果未能解决你的问题,请参考以下文章