需要帮助来编写查询
Need help to write a query
我需要编写一个查询来获取分配给特定项目的任期。
我有一个 table 的日常活动,它以以下格式存储公司中每个人的数据以及他们对项目的分配。
这里显示员工E123每天在各种项目上的分配情况。
查询应return未分配员工的开始日期和结束日期。
例如。在上述情况下,它应该 return
按项目分组 return 只有一条记录的开始日期为 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
认为这就是您要找的:
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
一种不同的(也是更常见的)方法是使用 ROW_NUMBER
和 CTE 创建孤岛(组)。这避免了对您的数据进行第二次扫描 table。然后,您可以对员工和组进行分组以获得最小值和最大值:
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,提供可消耗的样本数据。)
对我来说,这看起来像是一个相对简单的聚合查询。唯一的挑战是识别组。
不过,那也简单。它只是非 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<>fiddle.
试试这个 >>
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
我需要编写一个查询来获取分配给特定项目的任期。
我有一个 table 的日常活动,它以以下格式存储公司中每个人的数据以及他们对项目的分配。
这里显示员工E123每天在各种项目上的分配情况。
查询应return未分配员工的开始日期和结束日期。 例如。在上述情况下,它应该 return
按项目分组 return 只有一条记录的开始日期为 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
认为这就是您要找的:
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
一种不同的(也是更常见的)方法是使用 ROW_NUMBER
和 CTE 创建孤岛(组)。这避免了对您的数据进行第二次扫描 table。然后,您可以对员工和组进行分组以获得最小值和最大值:
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,提供可消耗的样本数据。)
对我来说,这看起来像是一个相对简单的聚合查询。唯一的挑战是识别组。
不过,那也简单。它只是非 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<>fiddle.
试试这个 >>
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