Oracle SQL检查值是否仅基于开始和结束

noj0wjuj  于 2023-05-06  发布在  Oracle
关注(0)|答案(2)|浏览(132)

根据下表
表1
| 批次起始编号|REG_N_START|批次至N|PREF_REG_N|
| --------------|--------------|--------------|--------------|
| 500万|CAL0001|5000019|CAL|
| 5000050|CAL0031|5000059|CAL|
| 5000100|CAL0299|5000105|CAL|
第1行将生成20个REG_N作为CAL0001,CAL0002,CAL0003,CAL0004,CAL0005,CAL0006,CAL0007,CAL0008,CAL0009,CAL0010,CAL0011,CAL0012,CAL0013,CAL0014,CAL0015,CAL0016,CAL0017,CAL0018,CAL0019,CAL0020
第2行将生成10个REG_N作为CAL0031,CAL0032,CAL0033,CAL0034,CAL0035,CAL0036,CAL0037,CAL0038,CAL0039,CAL0040
第3行将生成6个REG_N作为CAL0299,CAL0300,CAL0301,CAL0302,CAL0303,CAL0304
给定用户将尝试捕获的新范围(开始和结束),我需要查看上表中是否存在任何REG_NUM,并按如下方式通过/失败:
预期结果
| NEW_REG_NUM_FROM|新注册编号至|结果_预期|
| --------------|--------------|--------------|
| CAL0006|公司简介|未通过|
| CAL0019|CAL0025|未通过|
| CAL0025|CAL0025|通过|
| CAL0025|CAL0027|通过|
| CAL0027|CAL0036|未通过|
| CAL0100|CAL0300|未通过|
| CAL0100|CAL0200|通过|
我尝试了这个SQL,但它显然会失败:

SELECT count(*)
FROM   TABLE1
WHERE  TABLE1.REG_N_START <= NEW_REG_NUM_TO
AND    TABLE1.REG_N_START >= NEW_REG_NUM_FROM;
eblbsuwk

eblbsuwk1#

您可以将初始表转换为范围,然后查找重叠:

WITH new_data (NEW_REG_NUM_FROM, NEW_REG_NUM_TO) AS (
  SELECT 'CAL0006', 'CAL0008' FROM DUAL UNION ALL
  SELECT 'CAL0019', 'CAL0025' FROM DUAL UNION ALL
  SELECT 'CAL0025', 'CAL0025' FROM DUAL UNION ALL
  SELECT 'CAL0025', 'CAL0027' FROM DUAL UNION ALL
  SELECT 'CAL0027', 'CAL0036' FROM DUAL UNION ALL
  SELECT 'CAL0100', 'CAL0300' FROM DUAL UNION ALL
  SELECT 'CAL0100', 'CAL0200' FROM DUAL
),
t1_ranges (reg_n_start, reg_n_end) AS (
  SELECT reg_n_start,
         pref_reg_n
         || LPAD(
              TO_NUMBER(SUBSTR(reg_n_start, LENGTH(pref_reg_n) + 1))
                + batch_to_n - batch_from_n,
              4,
             '0'
            )
  FROM   table1
)
SELECT n.*,
       CASE
       WHEN EXISTS(
              SELECT 1
              FROM   t1_ranges t
              WHERE  t.reg_n_start <= n.new_reg_num_to
              AND    n.new_reg_num_from <= t.reg_n_end   
            )
       THEN 'FAIL'
       ELSE 'PASS'
       END AS result
FROM   new_data n

其中,对于样本数据:

CREATE TABLE TABLE1 (BATCH_FROM_N, REG_N_START, BATCH_TO_N, PREF_REG_N) AS
SELECT 5000000, 'CAL0001', 5000019, 'CAL' FROM DUAL UNION ALL
SELECT 5000050, 'CAL0031', 5000059, 'CAL' FROM DUAL UNION ALL
SELECT 5000100, 'CAL0299', 5000105, 'CAL' FROM DUAL;

输出:
| NEW_REG_NUM_FROM|新注册编号至|结果|
| --------------|--------------|--------------|
| CAL0006|公司简介|未通过|
| CAL0019|CAL0025|未通过|
| CAL0025|CAL0025|通过|
| CAL0025|CAL0027|通过|
| CAL0027|CAL0036|未通过|
| CAL0100|CAL0300|未通过|
| CAL0100|CAL0200|通过|
小提琴

rqdpfwrv

rqdpfwrv2#

我会尝试类似下面的东西:

with tb (new_regnum_from, new_regnum_to) as (
  select 'CAL0006', 'CAL0008' from dual union all
  select 'CAL0019', 'CAL0025' from dual union all
  select 'CAL0025', 'CAL0025' from dual union all   
  select 'CAL0025',     'CAL0027' from dual 
)
,tb_intervs as (
select reg_start_n, batch_to_n, batch_from_n
  ,subsr(reg_start_n,1,length(pref_reg_n)) ||
    lpad(to_char((substr(reg_start_n,length(pref_reg_n)+1,100)+batch_to_n-batch_from_n),length(reg_start_n)-length(pref_reg_n),'0') upper_lim_n
from table1
)
select new_regnum_from, new_regnum_to  
  ,case
    when exists (
      select 1
      from tb_intervs t1 
      where4 (new_regnum_from between t1.reg_start_n and t1.upper_lim_n) 
        or (new_regnum_to between t1.reg_start_n and t1.upper_lim_n)
      ) then 'FAIL'
    else 'PASS'
  end test_result
from tb

;
其实我还没有试过……首先要测试的是以下各项的回报:

select reg_start_n, batch_to_n, batch_from_n
  ,subsr(reg_start_n,1,length(pref_reg_n)) ||
    lpad(to_char((substr(reg_start_n,length(pref_reg_n)+1,100)+batch_to_n-batch_from_n),length(reg_start_n)-length(pref_reg_n),'0') upper_lim_n
from table1m_n

在用作CTE的此选择中可能存在一些错误...希望这会有所帮助。最后为我称为CTE的对象创建一个名为tb_intervs的视图。

相关问题