2011-03-04 64 views
1

考慮以下幾點:SQL - 需要確定隱式結束日期提供的開始日期

CREATE TABLE Members 
(
    MemberID CHAR(10) 
    , GroupID CHAR(10) 
    , JoinDate DATETIME 
) 

INSERT Members VALUES ('1', 'A', 2010-01-01) 
INSERT Members VALUES ('1', 'C', 2010-09-05) 
INSERT Members VALUES ('1', 'B', 2010-04-15) 
INSERT Members VALUES ('1', 'B', 2010-10-10) 
INSERT Members VALUES ('1', 'A', 2010-06-01) 
INSERT Members VALUES ('1', 'D', 2001-11-30) 

會是什麼,從這個表中選擇的最佳方式,確定隱含「LeaveDate」,產生了下面的數據集:

MemberID GroupID JoinDate LeaveDate 
1  A  2010-01-01 2010-04-14 
1  B  2010-04-15 2010-05-31 
1  A  2010-06-01 2010-09-04 
1  C  2010-09-05 2010-10-09 
1  B  2010-10-10 2010-11-29 
1  D  2010-11-30 NULL 

正如您所看到的,假設成員沒有失效。每個成員身份期間的[LeaveDate]假定爲下一個按時間順序排列的[JoinDate]之前一天,該成員可以在不同組中找到該成員。當然,這是我的實際問題的簡單說明,其中包括更多的分類/分組列和數千個不同成員,其中[JoinDate]值的存儲順序不特定。

+0

難道他們都應該有相同的'MemberID'? 'LeaveDate'如何確定? – FrustratedWithFormsDesigner 2011-03-04 14:59:33

回答

2

也許這樣的事情?自加入,並選擇大於當前行的加入日期的最小加入日期 - 即離職日期加1。從它減去一天。

您可能需要調整特定RDBMS的日期算術。

SELECT 
     m1.* 
    , MIN(m2.JoinDate) - INTERVAL 1 DAY AS LeaveDate 
FROM 
    Members m1 
LEFT JOIN 
    Members m2 
ON m2.MemberID = m1.MemberID 
AND m2.JoinDate > m1.JoinDate 
GROUP BY 
     m1.MemberID 
    , m1.GroupID 
    , m1.JoinDate 
ORDER BY 
     m1.MemberID 
    , m1.JoinDate 
+0

這個效果很好。謝謝。 – 2011-03-04 20:10:34

0

標準(ANSI)SQL解決方案:

 
SELECT memberid, 
     groupid, 
     joindate, 
     lead(joindate) OVER (PARTITION BY memberid ORDER BY joindate ASC) AS leave_date 
FROM members 
ORDER BY joindate ASC 
+0

我正在拍攝ANSI標準代碼,但是在MSSQL 2008中似乎沒有支持LEAD()OVER()。感謝您的建議。看起來像一個非常優雅的解決方案。 – 2011-03-04 20:10:13

+0

@ Rich.Carpenter:你沒有說明你的DBMS和所有DBMS都支持lead()和lag();) – 2011-03-04 20:47:13

相關問題