-1

我有一个名为 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)
4

1 回答 1

1

考虑到忽略一组(的VACW)中的间隙并容忍重复值的新要求,您提供的查询有两个问题。

  1. 它只被分割了empnum两次。这不会返回有用的结果。相反,您需要第二个按empnum, doecode.

  2. 由于需要按 分区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
;

看到这个在 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
;
于 2013-05-10T19:59:18.307 回答