Sql server SQL Server T-SQL:根据优先级值startdate和enddate获取记录集
我在做一个考勤系统。我必须填写以下表格: 计划:包含名称nvarchar字段以及开始和结束日期时间字段。 策略:也包含开始和结束日期时间字段。 PolicySchedule交叉表:在外键旁边包含优先级int字段。 End datetime字段可为空,表示开放期间 最高优先级的计划将在其时间和策略时间内应用和激活 我需要获得每个策略中应用的计划列表,以及它们的激活周期开始和结束时间,知道计划可能是交叉的。这里不涉及政策 例如:Sql server SQL Server T-SQL:根据优先级值startdate和enddate获取记录集,sql-server,tsql,Sql Server,Tsql,我在做一个考勤系统。我必须填写以下表格: 计划:包含名称nvarchar字段以及开始和结束日期时间字段。 策略:也包含开始和结束日期时间字段。 PolicySchedule交叉表:在外键旁边包含优先级int字段。 End datetime字段可为空,表示开放期间 最高优先级的计划将在其时间和策略时间内应用和激活 我需要获得每个策略中应用的计划列表,以及它们的激活周期开始和结束时间,知道计划可能是交叉的。这里不涉及政策 例如: 获取请求结果的最有效方法是什么?假设您使用的是SQL Server 2
获取请求结果的最有效方法是什么?假设您使用的是SQL Server 2005或更高版本,您可以使用外部应用程序来查找具有最高优先级的策略:
select *
from Schedule s
outer apply
(
select top 1 *
from PolicySchedule ps
join Policy p
on p.id = ps.policyid
where s.StartTime <= p.EndTime
and p.StartTime <= s.EndTime
order by
ps.priority desc
) pol
如果有必须重叠的时间段,您可以在外部应用中添加where子句。如果您有许多单独的策略和计划,但每个策略的计划很少,最简单的方法将非常有效:
WITH dates (policyId, changeDate) AS
(
SELECT policyId, changeDate,
ROW_NUMBER() OVER (PARTITION BY policyId ORDER BY changeDate) AS rn
FROM (
SELECT policyId, startDate AS changeDate
FROM policySchedule ps
JOIN schedule s
ON s.id = ps.scheduleId
UNION
SELECT policyId, endDate AS changeDate
FROM policySchedule ps
JOIN schedule s
ON s.id = ps.scheduleId
) q
),
ranges (startDate, endDate)AS
(
SELECT d1.policyId,
d1.changeDate,
d2.changeDate
FROM dates d1
JOIN dates d2
ON d2.policyId = d1.policyId
AND d2.rn = d1.rn + 1
)
SELECT *
FROM policy p
JOIN ranges r
ON r.policyId = p.id
CROSS APPLY
(
SELECT TOP 1 s.*
FROM policySchedules ps
JOIN schedule s
ON ps.policyId = p.id
AND s.id = ps.scheduleId
WHERE ps.startDate BETWEEN r.startDate AND r.endDate
AND ps.endDate BETWEEN r.startDate AND r.endDate
ORDER BY
ps.Priority DESC
)
开始时间和结束时间在策略上也可以相交吗?@Quassnoi:不,策略是独立的。我需要每个策略的结果集。这不考虑策略的生效日期。如果我正确,这将返回每个计划的最高优先级策略。我真正想要的是每个策略的应用/活动计划部分。。。
WITH dates (policyId, changeDate) AS
(
SELECT policyId, changeDate,
ROW_NUMBER() OVER (PARTITION BY policyId ORDER BY changeDate) AS rn
FROM (
SELECT policyId, startDate AS changeDate
FROM policySchedule ps
JOIN schedule s
ON s.id = ps.scheduleId
UNION
SELECT policyId, endDate AS changeDate
FROM policySchedule ps
JOIN schedule s
ON s.id = ps.scheduleId
) q
),
ranges (startDate, endDate)AS
(
SELECT d1.policyId,
d1.changeDate,
d2.changeDate
FROM dates d1
JOIN dates d2
ON d2.policyId = d1.policyId
AND d2.rn = d1.rn + 1
)
SELECT *
FROM policy p
JOIN ranges r
ON r.policyId = p.id
CROSS APPLY
(
SELECT TOP 1 s.*
FROM policySchedules ps
JOIN schedule s
ON ps.policyId = p.id
AND s.id = ps.scheduleId
WHERE ps.startDate BETWEEN r.startDate AND r.endDate
AND ps.endDate BETWEEN r.startDate AND r.endDate
ORDER BY
ps.Priority DESC
)