这就是我的表格的样子。我想为每个mcode只显示一行。 这里的规则是 对于AType =开始里程碑,我们必须采取MIN(StartDate)和for AType =完成里程碑考虑最大值(EndDate)。
PID AId Mcode AType StartDate EndDate
1 ABC1 PM105 Start Milestone 2013-08-12 00:00:00.000 NULL
1 ABC2 PM200 Start Milestone 2015-06-22 00:00:00.000 NULL
1 ABC3 PM200 Start Milestone 2014-08-25 00:00:00.000 NULL
1 ABC4 PM200 Start Milestone 2014-09-29 00:00:00.000 NULL
1 ABC5 PM200 Start Milestone 2014-08-11 00:00:00.000 NULL
1 ABC6 PM200 Start Milestone 2014-08-11 00:00:00.000 NULL
1 ABC7 PM235 Finish Milestone NULL 2015-11-10 00:00:00.000
1 ABC8 PM235 Finish Milestone NULL 2015-11-18 00:00:00.000
1 ABC9 PM235 Finish Milestone NULL 2015-11-10 00:00:00.000
1 ABC10 PM235 Finish Milestone NULL 2015-09-03 00:00:00.000
1 ABC11 PM235 Finish Milestone NULL 2016-02-25 00:00:00.000
1 ABC12 WM310 Finish Milestone NULL 2017-09-29 00:00:00.000
我的输出应该如下:
PID AId Mcode AType StartDate EndDate
1 ABC1 PM105 Start Milestone 2013-08-12 00:00:00.000 NULL
1 ABC6 PM200 Start Milestone 2014-08-11 00:00:00.000 NULL
1 ABC11 PM235 Finish Milestone NULL 2016-02-25 00:00:00.000
1 ABC12 WM310 Finish Milestone NULL 2017-09-29 00:00:00.000
您可以使用以下sql脚本:
Create table MilestoneData
(
ProjectID int,
ActivityId varchar(10),
MileStoneCode varchar(5),
ActivityType varchar(50),
StartDate datetime,
EndDate Datetime)
insert into MilestoneData values(1,'ABC1','PM105','Start Milestone','2013-08-12 00:00:00.000',NULL)
insert into MilestoneData values(1,'ABC2','PM200','Start Milestone','2015-06-22 00:00:00.000',NULL)
insert into MilestoneData values(1,'ABC3','PM200','Start Milestone','2014-08-25 00:00:00.000',NULL)
insert into MilestoneData values(1,'ABC4','PM200','Start Milestone','2014-09-29 00:00:00.000',NULL)
insert into MilestoneData values(1,'ABC5','PM200','Start Milestone','2014-08-11 00:00:00.000',NULL)
insert into MilestoneData values(1,'ABC6','PM200','Start Milestone','2014-08-11 00:00:00.000',NULL)
insert into MilestoneData values(1,'ABC7','PM235','Finish Milestone',NULL,'2015-11-10 00:00:00.000')
insert into MilestoneData values(1,'ABC8','PM235','Finish Milestone',NULL,'2015-11-18 00:00:00.000')
insert into MilestoneData values(1,'ABC9','PM235','Finish Milestone',NULL,'2015-11-10 00:00:00.000')
insert into MilestoneData values(1,'ABC10','PM235','Finish Milestone',NULL,'2015-09-03 00:00:00.000')
insert into MilestoneData values(1,'ABC11','PM235','Finish Milestone',NULL,'2016-02-25 00:00:00.000')
insert into MilestoneData values(1,'ABC12','WM310','Finish Milestone',NULL,'2017-09-29 00:00:00.000')
答案 0 :(得分:3)
试试这样:
WITH DistinctMileStoneCodes AS
(
SELECT DISTINCT ProjectID,MileStoneCode
FROM MilestoneData
)
SELECT dms.ProjectID
,dms.MileStoneCode
,StartAndFinish.*
FROM DistinctMileStoneCodes AS dms
CROSS APPLY
(
SELECT TOP 1 x.ActivityId,x.ActivityType,x.StartDate,x.EndDate FROM MilestoneData AS x WHERE x.ProjectID=dms.ProjectID AND x.MileStoneCode=dms.MileStoneCode AND ActivityType='Start Milestone' ORDER BY StartDate ASC
UNION SELECT TOP 1 x.ActivityId,x.ActivityType,x.StartDate,x.EndDate FROM MilestoneData AS x WHERE x.ProjectID=dms.ProjectID AND x.MileStoneCode=dms.MileStoneCode AND ActivityType='Finish Milestone' ORDER BY EndDate DESC
) AS StartAndFinish
结果
ProjectID MileStoneCode ActivityID ActivityType StartDate EndDate
1 PM105 ABC1 Start Milestone 2013-08-12 NULL
1 PM200 ABC5 Start Milestone 2014-08-11 NULL
1 PM235 ABC11 Finish Milestone NULL 2016-02-25
1 WM310 ABC12 Finish Milestone NULL 2017-09-29
答案 1 :(得分:2)
解决此问题的一种方法是使用窗口函数ROW_NUMBER对记录进行排名。
在这里,我添加了一个在CTE内计算的起点和终点排名。我使用CTE有两个原因。首先,您可以更轻松地独立运行查询并查看其工作原理。其次,您不能直接在WHERE子句中使用窗口函数。
WHERE子句使用CASE表达式来选择要过滤的排名字段。在这两种情况下,我们都希望得到最低等级(1)。
示例
WITH Ranked AS
(
/* CTE ranks each record based on Start and End dates.
*/
SELECT
ROW_NUMBER() OVER (PARTITION BY MileStoneCode ORDER BY StartDate ASC) AS StartRank,
ROW_NUMBER() OVER (PARTITION BY MileStoneCode ORDER BY EndDate DESC) AS EndRank,
ms.*
FROM
MilestoneData AS ms
)
SELECT
*
FROM
Ranked
WHERE
/* Case expression returns only the first ranked record,
* where ranking field is based on MileStonCode.
*/
CASE MileStoneCode
WHEN 'Start Milestone' THEN StartRank
ELSE EndRank
END = 1
;
值得强调的是,在使用CTE时,必须使用分号终止任何前面的语句。
答案 2 :(得分:1)
你想要这样的东西:
SELECT MileStoneCode,
MIN(StartDate)
FROM MilestoneData
WHERE ActivityType = 'Start Milestone'
GROUP BY MileStoneCode;
SELECT MileStoneCode,
MAX(EndDate)
FROM MilestoneData
WHERE ActivityType = 'Finish Milestone'
GROUP BY MileStoneCode;
点击此处的小提琴:http://sqlfiddle.com/#!9/edb508/7
答案 3 :(得分:1)
这应该产生你正在寻找的东西(根据你提供的创建脚本运行它):
SELECT projectID, ActivityId, MilestoneCode, ActivityType, startdate,
enddate
FROM MilestoneData
WHERE MilestoneCode + Right(activityId, Len(activityid)-3) + Cast(startdate AS VARCHAR) IN
(SELECT MilestoneCode + Cast(Max(Cast(Right(activityid, Len(activityid)-3) AS INT)) AS VARCHAR) + Cast(Min(startdate) AS VARCHAR)
FROM MilestoneData
WHERE activityType = 'Start Milestone'
GROUP BY milestonecode)
UNION SELECT projectID, ActivityId, MilestoneCode, ActivityType, startdate, enddate
FROM MilestoneData
WHERE MilestoneCode + Right(activityId, Len(activityid)-3) + Cast(enddate AS VARCHAR) IN
(SELECT MilestoneCode + Cast(Max(Cast(Right(activityid, Len(activityid)-3) AS INT)) AS VARCHAR) + Cast(Max(enddate) AS VARCHAR)
FROM MilestoneData
WHERE activityType = 'Finish Milestone'
GROUP BY milestonecode)
编辑:更正声明