我需要编写查询以获取对特定项目的任期。
我有一张日常活动表,该表以以下格式存储公司中每个人的数据及其在项目中的分配。
这显示员工E123每天在各个项目上的分配。
查询应返回未分配员工的开始日期和结束日期。 例如。在上述情况下,它应返回
按项目分组仅返回一条记录,开始日期为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
答案 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