需要帮助来编写查询

时间:2019-08-27 09:21:56

标签: sql sql-server date sql-date-functions

我需要编写查询以获取对特定项目的任期。

我有一张日常活动表,该表以以下格式存储公司中每个人的数据及其在项目中的分配。

Refer attached image for table format

这显示员工E123每天在各个项目上的分配。

查询应返回未分配员工的开始日期和结束日期。 例如。在上述情况下,它应返回

Attached image2

按项目分组仅返回一条记录,开始日期为2019年6月21日,结束日期为2019年6月27日,任期为7天,这是错误的。

尝试过这个:

select EmpCode, ProjectId, min(Date), max(Date), count(EmpCode)
where Date between cast('2019-04-01 00:00:00.000' as datetime) and getdate() --and s.ProjectId = 0
        and EmpId = 'E123'
group by EmpCode, ProjectId, Date

4 个答案:

答案 0 :(得分:1)

另一种(也是更常见的)方法是使用ROW_NUMBER和CTE创建岛(组)。这样可以避免对数据表进行第二次扫描。然后,您可以对员工和组进行分组以获取最小值和最大值:

DECLARE @Data table (EmpId char(6),
                     ProjectId char(2),
                     [Date] date);

INSERT INTO @Data (EmpId,
                   ProjectId,
                   Date)
VALUES ('EMP123', 'P1', '2019-06-18'),
       ('EMP123', 'P1', '2019-06-19'),
       ('EMP123', 'P1', '2019-06-20'),
       ('EMP123', NULL, '2019-06-21'),
       ('EMP123', NULL, '2019-06-22'),
       ('EMP123', NULL, '2019-06-23'),
       ('EMP123', 'P2', '2019-06-24'),
       ('EMP123', 'P2', '2019-06-25'),
       ('EMP123', NULL, '2019-06-26'),
       ('EMP123', NULL, '2019-06-27');

WITH Grps AS (
    SELECT D.EmpId,
           D.ProjectId,
           D.[Date],
           ROW_NUMBER() OVER (PARTITION BY D.EmpId ORDER BY D.Date) -
           ROW_NUMBER() OVER (PARTITION BY D.EmpId, D.ProjectId ORDER BY D.Date) AS Grp
    FROM @Data D)
SELECT G.EmpId,
       MIN(G.[Date]) AS StartDate,
       MAX(G.[Date]) AS EndDate,
       DATEDIFF(DAY,MIN(G.[Date]),MAX(G.[Date]))+1 AS Tenure
FROM Grps G
WHERE G.ProjectId IS NULL
GROUP BY G.EmpId,
         G.Grp;

(感谢Koen Vissers,提供了消耗品样本数据。)

答案 1 :(得分:0)

这就是您要寻找的东西:

DECLARE @Data TABLE
    (
    EmpId nVARCHAR(8),
    ProjectId nVARCHAR(3),
    Date DATE
    )

INSERT INTO @Data
(EmpId, ProjectId, Date)
VALUES
('EMP123', 'P1', '2019-06-18'),
('EMP123', 'P1', '2019-06-19'),
('EMP123', 'P1', '2019-06-20'),
('EMP123', NULL, '2019-06-21'),
('EMP123', NULL, '2019-06-22'),
('EMP123', NULL, '2019-06-23'),
('EMP123', 'P2', '2019-06-24'),
('EMP123', 'P2', '2019-06-25'),
('EMP123', NULL, '2019-06-26'),
('EMP123', NULL, '2019-06-27')

SELECT 
    MIN(d.Date) As StartDate,
    ISNULL(EndDate, MAX(Date)) As EndDate,
    DATEDIFF(d, MIN(d.Date), ISNULL(EndDate, MAX(Date))) + 1 As Tenure
FROM @Data d 
OUTER APPLY (SELECT TOP 1 DATEADD(d, -1, Date) As EndDate FROM @Data a WHERE a.EmpId = d.EmpId AND a.ProjectId IS NOT NULL AND a.Date > d.Date ORDER BY a.Date ASC) EndDate
WHERE
    d.ProjectId IS NULL
GROUP BY d.EmpId, d.ProjectId, EndDate

答案 2 :(得分:0)

对我来说,这看起来像是一个相对简单的聚合查询。唯一的挑战是确定组。

但是,这也很简单。它只是非NULL projectid值的累积数量:

select empid, min(date), max(date), count(*) as tenure
from (select d.*,
             count(projectid) over (partition by empid order by date) as grp
      from @data d
     ) d
where projectid is null
group by empid, grp
order by empid, min(date);

Here是db <>小提琴。

答案 3 :(得分:0)

尝试这个>>

    SELECT EMP_PRO.EmpCode,
       EMP_PRO.ProjectId,
       Date_M.min_D StartDate,
       Date_M.max_D EndDate,
       Date_M.tenure
  FROM EMP_PRO
       LEFT OUTER JOIN
       (SELECT min (date) min_D, max (Date) max_D, count (Grp) tenure , ProjectId
          FROM (SELECT id,
                       ProjectId,
                       date,
                         DENSE_RANK () OVER (ORDER BY id)
                       - DENSE_RANK ()
                            OVER (PARTITION BY ProjectId ORDER BY id)
                          AS Grp
                  FROM EMP_PRO) T
        GROUP BY T.Grp ,ProjectId) Date_M
          ON EMP_PRO.date = Date_M.min_D
 WHERE Date_M.min_D IS NOT NULL AND EMP_PRO.ProjectId IS NULL