我有一张名为timedetail的表,其中输入了工作时间(doecode w)或休假时间(doecode vac)。这是我到目前为止所做的,但它也正在恢复工作时间。
TimeDetail
empnum tsdate doecode
123 1/1/2013 VAC
123 1/2/2013 VAC
123 1/3/2013 VAC
123 1/4/2013 VAC
123 1/5/2013 VAC
123 1/6/2013 W
123 1/7/2013 W
123 1/8/2013 W
123 1/9/2013 VAC
111 1/1/2013 W
111 1/2/2013 VAC
111 1/3/2013 W
111 1/4/2013 VAC
111 1/5/2013 VAC
empnum 123应该返回但不是111
WITH R AS (
SELECT
empnum, tsdate,
ROW_NUMBER() OVER (PARTITION BY empnum ORDER BY tsdate)
- ROW_NUMBER() OVER (PARTITION BY empnum ORDER BY tsdate, doecode) as grp
FROM
timedetail t
WHERE
doecode in ('VAC')
-- and not exists (
-- select * from timedetail b where doecode < ' '
-- and b.tsdate = t.tsdate and b.empnum = t.empnum
-- )
)
SELECT empnum, MIN(tsdate) AS fdt, MAX(tsdate) AS tdt, COUNT(*) AS no_of_days
FROM R
GROUP BY empnum, grp
HAVING COUNT(*) > 4
ORDER BY empnum, MIN(tsdate), MAX(tsdate)
答案 0 :(得分:1)
鉴于忽略组(VAC
或W
)中的差距并容忍重复值的新要求,您提供的查询有两个问题。
仅按empnum
分区两次。这不会返回有用的结果。相反,您需要第二个按empnum, doecode
进行分区。
由于需要按doecode
进行分区,因此您无法从派生表中排除任何doecode
值,并且必须将WHERE doecode = 'VAC'
移出到主查询中。
我已在以下查询中解决了这些问题:
WITH R AS (
SELECT
T.*,
Grp =
DENSE_RANK() OVER (PARTITION BY T.empnum ORDER BY T.tsdate)
- DENSE_RANK() OVER (PARTITION BY T.empnum, T.doecode ORDER BY T.tsdate)
-- the subtracted value has to partition by doecode
FROM
dbo.TimeDetail T
)
SELECT
empnum,
FromDate = MIN(tsdate),
ToDate = MAX(tsdate),
DayCount = COUNT(DISTINCT tsdate)
FROM R
WHERE doecode = 'VAC' -- must be out here
GROUP BY empnum, grp
HAVING COUNT(DISTINCT tsdate) >= 5 -- distinct dates
ORDER BY
empnum,
FromDate
;
See this working in a SQL Fiddle
我使用>= 5
而不是> 4
,因为我认为它更清楚地表达了意图。
使用以下“棘手”的测试数据:
empnum tsdate doecode
------ ---------- -------
123 2013-01-01 VAC
123 2013-01-02 VAC
123 2013-01-03 VAC
123 2013-01-03 VAC -- duplicate row
123 2013-01-04 VAC
123 2013-01-04 VAC -- duplicate row
123 2013-01-07 VAC -- skipped a weekend
111 2013-01-01 W
111 2013-01-02 VAC
111 2013-01-03 W
111 2013-01-04 VAC
111 2013-01-06 W
111 2013-01-07 W
111 2013-01-08 W
111 2013-01-09 W
111 2013-01-10 W
这将返回:
empnum FromDate ToDate DayCount
------ ---------- ---------- --------
123 2013-01-01 2013-01-07 5
对于记录,如果您的数据是连续的且无法复制,则只需要一个Row_number
功能。对顺序项进行分组就像Itzik Ben-Gan的分组岛解决方案一样简单:
WITH R AS (
SELECT
T.*,
Grp = DateAdd(day,
-ROW_NUMBER() OVER (PARTITION BY T.empnum, T.doecode ORDER BY T.tsdate),
T.tsdate
)
FROM
dbo.TimeDetail T
WHERE
doecode in ('VAC')
)
SELECT
empnum,
FromDate = MIN(tsdate),
ToDate = MAX(tsdate),
DayCount = COUNT(*)
FROM R
GROUP BY empnum, grp
HAVING COUNT(*) >= 5
ORDER BY
empnum,
FromDate
;