我现在有一张表,自段位ID,name,startdate,其中startdate内容格式为‘201010’,现我想查询该表所有的人员,startdate不连续的信息。如:
1 smith 201001
2 smith 201002
3 smith 201004这个信息属于错误信息,我希望将它查询出来,不知道sql或procedure怎么写?
1 smith 201001
2 smith 201002
3 smith 201004这个信息属于错误信息,我希望将它查询出来,不知道sql或procedure怎么写?
解决方案 »
- ORACLE如何用SQL查出硬盘的剩余容量,分不多了,谢谢
- 如何删除重复项,保留一条记录
- 大家看看这种insert
- pl/sql 中, exception处理,when then之间可不可以什么也不写?
- 请教高手一个问题!!!!
- 急求,在线等,用asp操作oracle给表里添数据为什么出来的全是问号
- tmep表空间
- 这样实现自增数据类型啊eg00001~99999
- 急:联想万金T200服务器+Win2K Server 装不起Oracle数据库
- 创建资料档案库时,出现ORA-12500:TNS:监听程序无法启动专用服务器进程,百分赠!
- oracle存储过程返回值乱码问题
- 重装之前再看看有没有其他办法
WITH tab AS(
SELECT 1 id, 'smith'NAME, '201001'startdate FROM dual UNION ALL
SELECT 2, 'smith', '201002' FROM dual UNION ALL
SELECT 3, 'smith', '201004' FROM dual
),
tmp AS( --生产连续的日期临时表
SELECT To_Char(Add_Months(Trunc(SYSDATE,'yyyy'),LEVEL-1),'yyyymm') rq FROM dual
CONNECT BY LEVEL<=(SELECT To_Number(SubStr(Max(startdate),5,2)) FROM tab)
)
SELECT b.id, b.NAME,a.rq FROM tmp a,tab b
WHERE NOT EXISTS(SELECT 1 FROM tab WHERE a.rq=startdate)
ORDER BY 1
SQL>
SQL> with tableA as
2 (
3 select 1 id ,'smith' name, to_date('201001','yyyymm') startdate from dual union all
4 select 2 id ,'smith' name, to_date('201002','yyyymm') startdate from dual union all
5 select 3 id ,'smith' name, to_date('201004','yyyymm') startdate from dual
6 )
7 select *
8 from tableA a where name in
9 (select name
10 from tableA
11 group by name
12 having (max(startdate)-min(startdate))<>count(*))
13 ; ID NAME STARTDATE
---------- ----- -----------
3 smith 2010-4-1
2 smith 2010-2-1
1 smith 2010-1-1
with tb as
(select 1 id,'smith' name,'201001' startdate from dual union all
select 2,'smith','201002' from dual union all
select 3,'smith','201004' from dual)
select a.*
from tb a
where not exists(select 1 from tb b where a.name=b.name and a.startdate=b.startdate-1)
SQL>
SQL> with tb as
2 (select 1 id,'smith' name,'201001' startdate from dual union all
3 select 2,'smith','201002' from dual union all
4 select 3,'smith','201004' from dual)
5 select a.*
6 from tb a
7 where not exists(select 1 from tb b where a.name=b.name and a.startdate=b.startdate-1)
8 /
ID NAME STARTDATE
---------- ----- ---------
2 smith 201002
3 smith 201004
------上面的有点不对
SQL>
SQL> with tableA as
2 (
3 select 1 id ,'smith' name, to_date('201001','yyyymm') startdate from dual union all
4 select 2 id ,'smith' name, to_date('201002','yyyymm') startdate from dual union all
5 select 3 id ,'smith' name, to_date('201006','yyyymm') startdate from dual
6 )
7 select a.*
8 from tableA a
9 where exists
10 (select *
11 from (select name,
12 sum(case
13 when startdate = nextdate then
14 1
15 when startdate - add_months(nextdate, 1) = 0 then
16 1
17 else
18 0
19 end) cnt,
20 count(*) rowcnt
21 from (select id,
22 name,
23 startdate,
24 nvl(lag(startdate, 1)
25 over(partition by name order by startdate),
26 startdate) nextdate
27 from tableA) t
28 group by name) b
29 where a.name = b.name
30 and b.cnt <> b.rowcnt)
31 ; ID NAME STARTDATE
---------- ----- -----------
1 smith 2010-1-1
2 smith 2010-2-1
3 smith 2010-6-1SQL>
---数据测试
-------先按照name分组,按时间排序,使用lag函数找到上一行的时间为nextdate,
-------如果相差的时间为一个月,表示时间连续,然后和改分则的所有行数比较,如果相等,代表连续,不相-----等代表不连续
SQL> with tableA as
2 (
3 select 1 id ,'smith' name, to_date('201001','yyyymm') startdate from dual union all
4 select 2 id ,'smith' name, to_date('201002','yyyymm') startdate from dual union all
5 select 3 id ,'smith' name, to_date('201003','yyyymm') startdate from dual union all
6 select 4 id ,'Jokson' name, to_date('201001','yyyymm') startdate from dual union all
7 select 5 id ,'Jokson' name, to_date('201002','yyyymm') startdate from dual union all
8 select 6 id ,'Jokson' name, to_date('201009','yyyymm') startdate from dual
9 )
10 select a.*
11 from tableA a
12 where exists
13 (select *
14 from (select name,
15 sum(case
16 when startdate = nextdate then
17 1
18 when startdate - add_months(nextdate, 1) = 0 then
19 1
20 else
21 0
22 end) cnt,
23 count(*) rowcnt
24 from (select id,
25 name,
26 startdate,
27 nvl(lag(startdate, 1)
28 over(partition by name order by startdate),
29 startdate) nextdate
30 from tableA) t
31 group by name) b
32 where a.name = b.name
33 and b.cnt <> b.rowcnt)
34 ; ID NAME STARTDATE
---------- ------ -----------
4 Jokson 2010-1-1
5 Jokson 2010-2-1
6 Jokson 2010-9-1SQL>
FROM (SELECT 人员ID, startdate, lead(startdate) over(PARTITION BY 人员ID ORDER BY startdate) ldate
FROM 表)
WHERE ldate IS NOT NULL AND
add_months(to_date(startdate, 'yyyymmdd'), 1) <> to_date(ldate, 'yyyymmdd');使用分析函数lag或lead是较好的方法,如果数据量大,慢是不可避免的,上亿数据肯定是要有时间条件并且是分区的。要不然~~~~~~~~~~~
有了SQL,存储过程不难写了吧,你要怎么样使用临表都可以的。