我有一张表有类似下面的数据
Emp Date Code
--- -------- ----
E1 11/1/2012 W
E1 11/1/2012 V
E2 11/1/2012 W
E1 11/2/2012 W
E1 11/3/2012 W
E1 11/4/2012 W
E1 11/5/2012 W
我想获得一个日期范围(比如最近3个月)的员工列表,这些日期范围代表W连续工作了5天,输出中的日期范围。每位员工可以使用不同的代码在一天内拥有多条记录。
预期输出
Emp Date-Range
--- ----------
E1 11/1 -11/5
以下是我的尝试,但我并没有接近我寻求的输出
SELECT distinct user, MIN(date) startdate, MAX(date) enddate
FROM (SELECT user, date, (TRUNC(date) - ROWNUM) tmpcol
FROM (SELECT user, date
FROM tablename
where date between to_date('10/01/2012','mm/dd/yyyy') and to_date('10/03/2012','mm/dd/yyyy')
ORDER BY user, date) ot) t
GROUP BY user, tmpcol
ORDER BY user, startdate;
如果Emp E1连续工作了10天,他应该在输出中列出两次日期范围。如果E1连续工作9天(11/1至11/9),他应该只列出一次,日期范围为11/1到11/9。
我已经看到了类似的问题,但这些问题对我来说都没有。我的数据库是Oracle 10G,没有PL / SQL。
答案 0 :(得分:3)
你可以从这里开始:
select
emp, count(*) over (partition by emp, code order by date_worked range interval '5' day preceding) as days_worked_last_5_days
from table
where code='W';
具有days_worked_last_5_days = 5的行是您搜索的行。
答案 1 :(得分:2)
我不确定我是否理解了所有内容,但是这样的事情可能会让你开始:
select emp,
sum(diff) as days,
to_char(min(workdate), 'yyyy-mm-dd') as work_start,
to_char(max(workdate), 'yyyy-mm-dd') as work_end
from (
select *
from (
select emp,
workdate,
code,
nvl(workdate - lag(workdate) over (partition by emp, code order by workdate),1) as diff
from tablename
where code = 'W'
and workdate between ...
) t1
where diff = 1 -- only consecutive rows
) t2
group by emp
having sum(diff) = 5
SQLFiddle:http://sqlfiddle.com/#!4/ad7ae/3
请注意,我使用了workdate
而不是date
,因为使用保留字作为列名是个不错的主意。
答案 2 :(得分:0)
Select emp, data-5, data from (SELECT EMP, DATA, WORK,lag, lead, row_number() over(PARTITION BY emp--, DATA
ORDER BY DATA asc) rn
FROM (SELECT emp,
data,
work,
LAG (data) OVER (PARTITION BY emp ORDER BY data ASC) LAG,
LEAD (data) OVER (PARTITION BY emp ORDER BY data ASC) LEAD
FROM (SELECT emp,
data,
work,
ROW_NUMBER ()
OVER (PARTITION BY emp, data ORDER BY data ASC)
rn
FROM example)
WHERE rn = 1) a
WHERE a.data + 1 = LEAD AND a.data - 1 = LAG
) WHERE rn = 5
表示例如下:
EMP(varchar2),日期,'W'或'F'
答案 3 :(得分:0)
SELECT * FROM (
SELECT USERID,USEDATE,WRK,RANK() OVER (PARTITION BY USERID,WRK ORDER BY USEDATE ) AS RNK1 FROM USER1 )U1 JOIN
(
SELECT USERID,USEDATE,WRK,RANK() OVER (PARTITION BY USERID,WRK ORDER BY USEDATE ) AS RNK2 FROM USER1 )U2 ON U1.USERID=U2.USERID AND U1.RNK1+3=U2.RNK2 AND U2.USEDATE-U1.USEDATE=3;