表 A
qshm zzhm zt 1001 1010 zc
1003 1004 zf
1007 1007 zf 3条记录
正常使用号码为1001 到 1010
其中作废号码为1003 到 1004
1007 到 1007 需要正常 1001 1010 减去 1003 1004 和 1007 1007结果应该是
1001 - 1002
1005 - 1006
1008 - 1010
oracle 语句 或 过程
qshm zzhm zt 1001 1010 zc
1003 1004 zf
1007 1007 zf 3条记录
正常使用号码为1001 到 1010
其中作废号码为1003 到 1004
1007 到 1007 需要正常 1001 1010 减去 1003 1004 和 1007 1007结果应该是
1001 - 1002
1005 - 1006
1008 - 1010
oracle 语句 或 过程
SELECT 1001 qshm,1010 zzhm,'zc' zt FROM dual UNION all
SELECT 1003,1004,'zf' FROM dual UNION ALL
SELECT 1007,1007,'zf' FROM dual
),
b AS(SELECT qshm num FROM a UNION SELECT zzhm num FROM a ),
c AS(SELECT num,lead(num)over(ORDER BY 1) num2 FROM b)
SELECT decode(num-1,1000,num,num+1) num1,Decode(num2-1,1009,num2,num2-1) num2
FROM c WHERE num2-1!=num AND num!=num-1
QSHM ZZHM ZT
----- ----- ----------
1001 1010 zc
1003 1004 zf
1007 1007 zf
SQL>
SQL> with t1 as (select rownum-1 rn from dual connect by rownum<=(select max(zzhm-qshm) from tb1)),
2 t2 as (select qshm+rn qshm ,decode(zt,'zc',0,1) zt from tb1,t1 where tb1.qshm+t1.rn<=tb1.zzhm),
3 t3 as (select qshm,sum(zt) zt from t2 group by qshm having sum(zt)=0),
4 t4 as (select qshm,qshm+row_number()over(order by qshm desc) rn from t3)
5 select min(qshm),max(qshm) from t4 group by rn;
MIN(QSHM) MAX(QSHM)
---------- ----------
1001 1002
1005 1006
1008 1010
SQL>
create table A (qshm number(4),zzhm number(4),zt char(2))
/insert into A values(1001,1010,'zc');
insert into A values(1003,1004,'zf');
insert into A values(1007,1007,'zf');
commit;with t1 as(
select qshm hm,zt,0 st from A
union
select zzhm,zt,1 from A
),
t2 as(
select hm hm1, zt zt1,
lead(hm) over (order by rownum) hm2,
lead(zt) over (order by rownum) zt2,
lead(st) over (order by rownum) st2
from t1
),
t3 as(
select
decode(zt1,'zc',hm1,hm1+1) hm1,
decode(zt2,'zc',hm2,decode(st2,0,hm2-1,null)) hm2
from t2
)
select hm1,hm2 from t3 where hm2 is not null;
/*
1001 1002
1005 1006
1008 1010
*/drop table A purge
/
WITH TMP AS
(SELECT X.*,
LEAD(HM) OVER(ORDER BY HM) LD_HM,
LAG(HM) OVER(ORDER BY HM) LG_HM
FROM (SELECT HM,
FLAG,
LAG(FLAG) OVER(ORDER BY HM) LG,
LEAD(FLAG) OVER(ORDER BY HM) LD
FROM (SELECT QSHM - 1 HM, '1' FLAG
FROM A
WHERE ZT = 'zf'
UNION ALL
SELECT ZZHM + 1, '2' FROM A WHERE ZT = 'zf')) X
WHERE NVL(DECODE(FLAG, 1, LG, 2, LD), '0') <> FLAG)SELECT DISTINCT CASE T2.FLAG WHEN '1' THEN TO_CHAR (GREATEST(T1.QSHM,
NVL(T2.LG_HM,
-9999)), '9999') || '-' || TO_CHAR (T2.HM, '9999') ELSE TO_CHAR (T2.HM, '9999') || '-' || TO_CHAR (LEAST(T1.ZZHM,
NVL(T2.LD_HM,
9999)), '9999') END T
FROM A T1, TMP T2
WHERE T2.HM >= T1.QSHM AND T2.HM <= T1.ZZHM
ORDER BY T这个要分析多种可能性,比如如果zt为'zf'的其中两条记录的号码范围出现交集,则4楼的代码就会报错
如果固定号码为整数,且号码量不会太大,可以采取创建虚拟号码,根据条件来过滤掉不符合要求的部分,类似3楼的做法
WITH TMP AS
(SELECT ROWNUM + QSHM - 1 HM
FROM (SELECT MIN(QSHM) QSHM, MAX(ZZHM) ZZHM FROM A WHERE ZT = 'zc')
CONNECT BY ROWNUM <= ZZHM - QSHM + 1)
SELECT MIN (HM) || '-' || MAX (HM)
FROM (SELECT HM
FROM TMP T
WHERE EXISTS (SELECT 1
FROM A
WHERE T.HM BETWEEN QSHM AND ZZHM
AND ZT = 'zc')
AND NOT EXISTS (SELECT 1
FROM A
WHERE T.HM BETWEEN QSHM AND ZZHM
AND ZT = 'zf')
ORDER BY HM)
GROUP BY HM - ROWNUM
ORDER BY MIN (HM)
--trycreate or replace procedure pro_result
is
counter number;
type v_hm_table is table of a.zzhm%type
index by binary_integer;
v_hm v_hm_table;
type v_hm_table_zf is table of a.zzhm%type;
v_hm_zf v_hm_table_zf;
begin
v_hm_zf:=v_hm_table_zf(1003,1004,1007);
for i in 1001..1010 loop
v_hm(i-1000):=i;
end loop;
if v_hm is not null then
counter:=v_hm.first;
while counter <=10 loop for i in 1..3 loop
case when v_hm(counter) = v_hm_zf(i) then
v_hm.delete (counter);
counter:= v_hm.next(counter);
else
dbms_output.put_line(v_hm(counter));
counter:=v_hm.next(counter);
end case;
end loop;
end loop;
end if;
end;
--try
create or replace procedure pro_result
is
counter number;
type v_hm_table is table of a.zzhm%type
index by binary_integer;
v_hm v_hm_table;
type v_hm_table_zf is table of a.zzhm%type;
v_hm_zf v_hm_table_zf;
begin
v_hm_zf:=v_hm_table_zf(1003,1004,1007);
for i in 1001..1010 loop
v_hm(i-1000):=i;
end loop;
if v_hm is not null then
counter:=v_hm.first;
while counter <=10 loop for i in 1..3 loop
case when v_hm(counter) = v_hm_zf(i) then
v_hm.delete (counter);
counter:= v_hm.next(counter);
else
dbms_output.put_line(v_hm(counter));
counter:=v_hm.next(counter);
end case;
end loop;
end loop;
end if;
end;
SQL> CREATE OR REPLACE PROCEDURE check_hm
2 (i_zt varchar2,--号码状态
3 i_hm number, --check的号码
4 out_flg out number)--是否为合法号码的标志位:0,号码不合法,不输出;1,号码合法,输出。
5 IS
6 TYPE t IS TABLE OF a%ROWTYPE;
7 tmp_hm t;
8 BEGIN
9 SELECT * BULK COLLECT INTO tmp_hm FROM a
10 WHERE zt != i_zt;
11 out_flg := 1;
12 FOR j IN 1 .. tmp_hm.COUNT LOOP
13 IF i_hm >= tmp_hm(j).qshm AND i_hm <= tmp_hm(j).zzhm THEN
14 out_flg := 0;
15 END IF;
16 END LOOP;
17 END;
18 /Procedure createdSQL> CREATE OR REPLACE PROCEDURE get_hm
2 (i_zt varchar2) --查询号码的状态
3 IS
4 TYPE t IS TABLE OF a%ROWTYPE;
5 ret_hm t;
6 out_flg number := 0;
7 BEGIN
8 SELECT * BULK COLLECT INTO ret_hm FROM a
9 WHERE zt = i_zt;
10 FOR i IN 1 .. ret_hm.COUNT LOOP
11 FOR o IN ret_hm(i).qshm .. ret_hm(i).zzhm LOOP
12 out_flg := 1;
13 check_hm(i_zt,o,out_flg);--调用存储过程check_hm
14 IF out_flg = 1 THEN
15 DBMS_OUTPUT.PUT_LINE(o);
16 END IF;
17 END LOOP;
18 END LOOP;
19 END;
20 /Procedure createdSQL> --调用存储过程get_hm
SQL> exec get_hm('zc');1001
1002
1005
1006
1008
1009
1010PL/SQL procedure successfully completedSQL>
create or replace procedure pro_result
is
counter number;
type v_hm_table is table of a.zzhm%type
index by binary_integer;
v_hm v_hm_table;
type v_hm_table_zf is table of a.zzhm%type;
v_hm_zf v_hm_table_zf;
begin
v_hm_zf:=v_hm_table_zf(1003,1004,1007);
for i in 1001..1010 loop
v_hm(i-1000):=i;
end loop;
if v_hm is not null then
counter:=v_hm.first;
while counter <=10 loop for i in 1..3 loop
if v_hm(counter)=v_hm_zf(i) then
v_hm.delete (counter);
counter:=v_hm.next(counter);
else
null;
end if;
end loop;
dbms_output.put_line(v_hm(counter));
counter:=v_hm.next(counter);
end loop;
else
dbms_output.put_line('v_hm is null!');
end if;
end;