我有一张每年有日期范围(季节)的表格。 通常情况是,一个赛季的结束是下赛季的开始。 在下面的示例中,我以粗体显示了两个不规则的季节设置。在第一季结束时是第二季开始后的第二天。在第二季,第四季的开始是在第三季结束后的第二天
+--------+----+--------------+--------------+
|SEASONID|YEAR|DATE FROM |DATE TO |
+--------+----+--------------+--------------+
|1 |14 | 2014-01-01 |**2014-01-31**|
|2 |14 |**2014-01-30**| 2014-03-01 |
|3 |14 | 2014-03-01 |**2014-05-22**|
|4 |14 |**2014-05-23**| 2014-10-16 |
|5 |14 | 2014-10-16 | 2014-12-01 |
+--------+----+--------------+--------------+
有没有办法编写一个可以捕获未正确设置的季节的查询? (一个赛季结束的时间不是下一个赛季的开始)
答案 0 :(得分:3)
这回答了你问题的一半:使用this article中的重叠日期查询来查找冲突的记录:
-- 1.2) select date ranges that overlap [d1, d2) (d2 and end_date are exclusive)
-- SELECT * FROM <table> WHERE @d2 > start_date AND end_date > @d1
SELECT s1.*
FROM seasons AS s1
INNER JOIN seasons AS s2 ON s1.seasonid <> s2.seasonid
AND s2.date_to > s1.date_from
AND s1.date_to > s2.date_from
结果:
+--------+----+----------+----------+--------+----+----------+----------+
|seasonid|year|date_from |date_to |seasonid|year|date_from |date_to |
+--------+----+----------+----------+--------+----+----------+----------+
|1 |14 |2014-01-01|2014-01-31|2 |14 |2014-01-30|2014-03-01|
+--------+----+----------+----------+--------+----+----------+----------+
|2 |14 |2014-01-30|2014-03-01|1 |14 |2014-01-01|2014-01-31|
+--------+----+----------+----------+--------+----+----------+----------+
答案 1 :(得分:1)
我希望这会对你有所帮助
select * from stest st
join stest st1
on st.edate ! = st1.sdate
where st1.id = st.id + 1
其中stest具有以下细节
+--+----+----------+----------+
|id|year|sdate |edate |
+--+----+----------+----------+
|1 |14 |2014-01-01|2014-01-31|
+--+----+----------+----------+
|2 |14 |2014-01-30|2014-03-01|
+--+----+----------+----------+
|3 |14 |2014-03-01|2014-05-22|
+--+----+----------+----------+
|4 |14 |2014-05-23|2014-10-16|
+--+----+----------+----------+
|5 |14 |2014-10-16|2014-12-01|
+--+----+----------+----------+
以上查询将给出以下结果
+--+----+----------+----------+--+----+----------+----------+
|id|year|sdate |edate |id|year|sdate |edate |
+--+----+----------+----------+--+----+----------+----------+
|1 |14 |2014-01-01|2014-01-31|2 |14 |2014-01-30|2014-03-01|
+--+----+----------+----------+--+----+----------+----------+
|3 |14 |2014-03-01|2014-05-22|4 |14 |2014-05-23|2014-10-16|
+--+----+----------+----------+--+----+----------+----------+
结果你可以得到id(1,2)和(3,4)不匹配
如果你喜欢下面的话
select * from stest st
join stest st1
on st.edate = st1.sdate
where st1.id = st.id + 1
然后你会得到匹配的结果
+--+----+----------+----------+--+----+----------+----------+
|id|year|sdate |edateid |id|year|sdate |edate |
+--+----+----------+----------+--+----+----------+----------+
|2 |14 |2014-01-30|2014-03-01|3 |14 |2014-03-01|2014-05-22|
+--+----+----------+----------+--+----+----------+----------+
|4 |14 |2014-05-23|2014-10-16|5 |14 |2014-10-16|2014-12-01|
+--+----+----------+----------+--+----+----------+----------+
答案 2 :(得分:0)
一种特殊的蛮力方法:
SELECT *
FROM seasons s1
CROSS JOIN seasons s2
WHERE NOT (s1.date_to <= s2.date_from OR s1.date_from >= s2.date_to);
希望没有足够的记录来导致笛卡尔加入的性能问题。如果您有SQL Server 2012,可以使用窗口函数进行改进(仅比较相邻的季节)。
答案 3 :(得分:0)
DECLARE @T TABLE (
SeasonId INT NOT NULL,
Year INT NOT NULL,
DateFrom DATE NOT NULL,
DateTo DATE NOT NULL
)
INSERT @T VALUES (1, 14, '2014-01-01', '2014-01-31')
INSERT @T VALUES (2, 14, '2014-01-30', '2014-03-01')
INSERT @T VALUES (3, 14, '2014-03-01', '2014-05-22')
INSERT @T VALUES (4, 14, '2014-05-23', '2014-10-16')
INSERT @T VALUES (5, 14, '2014-10-16', '2014-12-01')
;WITH T AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY DateFrom) RowId
FROM @T
)
SELECT
A.SeasonId, A.DateTo,
B.SeasonId, B.DateFrom
FROM T A JOIN T B ON A.RowId + 1 = B.RowId
WHERE A.DateTo <> B.DateFrom