我有一个SQL Server 2008表,其数据如下:
Contract_No Property_No Start_Dte End_Dte
12345 123 01/01/2014 01/31/2014
12345 123 01/15/2014 02/15/2014
12345 123 03/01/2014 03/31/2014
12345 124 01/01/2014 01/31/2014
我不能拥有重叠日期范围的相同合约/物业#。因此,上面的第二行将是一个问题,因为它的Start_Dte
在第一行的日期范围的中间开始。所有其他行都没问题。
我真的对如何使用SQL查询执行此操作感到茫然。我知道如何使用像C#或VB这样的语言来检查这一点,但是我写的查询失败了。
有人有什么想法吗?
答案 0 :(得分:2)
以下查询将显示与其他记录(SQL Fiddle)存在冲突的日期范围的所有记录:
WITH x AS (
SELECT *,ROW_NUMBER() OVER (ORDER BY Contract_No, Property_No, Start_Dte) AS r
FROM MyTable
)
SELECT *
FROM x m1
INNER JOIN x m2
ON m2.Contract_No = m1.Contract_No
AND m2.Property_No = m1.Property_No
AND m1.r <> m2.r
AND
(
(
m2.Start_Dte >= m1.Start_Dte
AND m2.Start_Dte <= m1.End_Dte
) OR
(
m2.End_Dte >= m1.Start_Dte
AND m2.End_Dte <= m1.End_Dte
)
)
答案 1 :(得分:1)
(编辑)的
以下查询将生成一个合约/属性对列表,其中有两个或更多重叠句点:
SELECT distinct t1.Contract_No, t1.Property_No, t1.Start_Dte, t1.End_Dte
from MyTable t1
inner join MyTable t2
on t2.Contract_No = t1.Contract_No
and t2.Property_No = t1.Property_No
and t1.Start_Dte <> t2.Start_Dte -- PK check
and t1.End_Dte <> t2.End_Dte -- PK check
and t2.Start_Dte < t1.End_Dte
and t2.End_Dte > t1.Start_Dte
这对提供的样本数据起作用,但可能还有一些需要考虑的边缘情况,例如......
难看的难点在于,如果没有引用每一列,就无法唯一地识别表中的行...这意味着如果两行或多行具有相同的时间,则此查询不会捕获它们,并且您需要使用使用row-number
的其他解决方案之一。 (当然,没有主键,你也会遇到很多其他问题......)如果有可用的主键,可以用简单的主键检查替换两个-- PKcheck
行。
如上所述,我第一次没有得到这个Aztec Math的东西。以下是我最初的预调试响应。
以下查询将生成一个合约/属性对列表,其中有两个或更多重叠句点:
SELECT distinct t1.Contract_No, t1.Property_No
from MyTable t1
inner join MyTable t2
on t2.Contract_No = t1.Contract_No
and t2.Property_No = t1.Property_No
and (t2.Start_Dte > t1.End_Dte
or t2.End_Dte < t1.Start_Dte)
一定要测试逻辑,我总是发现在第一时间完全正确地获取这些时间查询很棘手。这个想法是
如果开始/停止日期可能重叠,请使用&gt; =和&lt; =。如果您使用的是datetime或smalldatetime数据类型,请小心 - 除了日期之外,您还将在值中有一个时间“元素”。
那是开始。下一步是列出所有合同/属性:
SELECT tt.* -- Being lazy here, you should always specify precisely which columns to return
from MyTable tt
inner join (-- Make it a subquery
select distinct t1.Contract_No, t1.Property_No
from MyTable t1
inner join MyTable t2
on t2.Contract_No = t1.Contract_No
and t2.Property_No = t1.Property_No
and (t2.Start_Dte > t1.End_Dte
or t2.End_Dte < t1.Start_Dte)) xx
on xx.Contract_No = tt.Contract_No
and xx.Property_No = tt.Property_No
接下来:确定合同错误。当然,这需要应用商业逻辑,将球放回你的球场。
答案 2 :(得分:1)
请试试这个
WITH cte AS (
SELECT *,ROW_NUMBER() OVER (ORDER BY [Contract_No], [Property_No], [Start_Dte]) AS row_num
FROM tbl
)
SELECT *
FROM cte t1
WHERE EXISTS(
SELECT 1
FROM cte t2
WHERE
t1.Contract_No = t2.Contract_No
AND t1.Property_No = t2.Property_No
AND t1.row_num > t2.row_num
AND (
(t1.Start_Dte BETWEEN t2.Start_Dte AND t2.End_Dte)
OR
(t1.END_Dte BETWEEN t2.Start_Dte AND t2.End_Dte)
)
)