2014-01-13 183 views
1

我有一個表格,每年的日期範圍(季節)。 正常情況下,一季的結束是下一季的開始。 在下面的例子中,我粗體顯示了兩個不規則的季節設置。在季節1的第一端部是季節2的beggining在第二後一天,季節4的beggining爲一天seaon 3SQL Server找到重疊日期範圍

+--------+----+--------------+--------------+ 
|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

ID是否是自動增量? – Backtrack

+0

這只是另一個孤島和空白的問題。嘗試使用Google搜索或搜索SO,您會發現問題描述和衆多答案。 – OzrenTkalcecKrznaric

+0

不幸的是,SeasonID是自動增量的,並且沒有規則每年都會按順序插入季節。這使所有的查詢取決於ID = ID + 1無用:( – PanosPlat

回答

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

這回答了你的問題的一半:使用重疊的日期查詢從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| 
+--------+----+----------+----------+--------+----+----------+----------+ 

SQL Fiddle

1

我希望這會幫助你

select * from stest st 
join stest st1 
on st.edate ! = st1.sdate 
where st1.id = st.id + 1 

- 其中具有以下細節

+--+----+----------+----------+ 
|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| 
+--+----+----------+----------+--+----+----------+----------+ 

從結果STEST你可以得到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| 
+--+----+----------+----------+--+----+----------+----------+ 
+0

Thanx很多,但UUThat每年將有其季節順序插入。這使得所有的查詢取決於ID = ID + 1無用:( – PanosPlat

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