2012-06-01 98 views
0

有資格[Eg]和不合格[In]的資格表[ET]中有記錄。每條記錄只有一個附加日期。我在服務表[ST]中有客戶服務[CS],我需要確定最近服務日期之前的記錄類型。查詢最近處理的記錄


______________ET______________ 



Eg 01.01.2012 
In 01.20.2012 
Eg 01.29.2012 
In 02.10.2012 

_________________________ST______________________________ 

CS Joe Schmoe 02.01.2012 11:00 AM 
CS Joe Schmoe 01.25.2012 1:00 PM 
CS Harold Doe 02.09.2012 4:00 PM 

我想回到一個事實,即在2012年1月2日上午11:00喬蠢貨服務是因爲01.01.2012的資格備案的資格,喬蠢貨是沒有資格2012年1月20日下午1:00,因爲2012年1月20日的資格不合格記錄,並且由於2012年9月2日的資格記錄,Harold Schmoe有資格獲得2012年9月2日下午4:00的服務。

__ _ __ _ __ _ __結果_ __ _ __ _ __ _ __ _ __ _ __

喬蠢貨2012年2月1日11:00 AM資格01.01.2012
喬蠢貨2012年1月25日下午1:00不合格的二○一二年一月二十〇日
哈羅德·多伊2012年9月2日4:00 PM不符合條件的2012年1月29日

+0

您的結果示例和您的描述似乎相互矛盾。 – Mithrandir

+0

因此,如果我理解正確,資格是打開或關閉。如果服務日期處於一段時間,則符合條件。如果它處於關閉期,則不是。那對嗎? – mikeY

+0

ST如何加入ET? –

回答

0

假設在用戶名和日期的合格表的唯一約束(否則,你需要另一個決勝局如添加ROW_NUMBER過的用戶ID,日期),您:

  • JOIN到有個約會小於所有記錄您感興趣的日期(CS日期)
  • Y然後取這些日期的最大值(因爲您想要事件發生前的最後一個日期)
  • 然後,您可以回到原始表格以獲取行詳細信息的其餘部分(狀態類型)。這就是爲什麼你需要的唯一約束

SELECT 
    UserId, Date, Status, ETDate 
FROM (
    --The last matching status record by date 
    SELECT ST.UserId, ST.Date, MAX(ET.Date) as ETDate 
    FROM ST 
    JOIN ET ON 
     ST.UserId = ET.UserId 
     AND CS.Date >= ET.Date 
    GROUP BY 
     ST.UserId, ST.Date 
) as C 
JOIN ET as E ON 
    C.UserId = E.UserId 
    AND C.ETDate = E.ETDate 
+0

沒有CS表,ET表中沒有用戶標識。對於我們這些顯然非常緩慢的人來說,你可以通過這個步驟嗎? – mikeY

+0

@mikeY - 對不起 - s/CS/ST。缺少模式信息,我假設連接應該在UserId上。如果合格/不合格是一個「全局」值,應該足夠簡單,只需從聯接中刪除UserId(並且您仍然需要日期中的唯一約束)。 –

0

這似乎是一個奇怪的要求,因爲elibility不是在用戶級別。

下面的查詢你想要做什麼:

select et.*, st.elibility, st.ETDate 
from et cross join 
    (select st.* 
     from st join 
      (SELECT MAX(cs.Date) as lastcsDate 
      FROM st JOIN 
       et 
       ON st.Date <= et.Date 
      GROUP BY cs.UserId 
      ) t 
      on st.date = t.lastcsDate 
    ) lastst 

注:我沒有運行此查詢原諒任何錯字。

這使用相關的子查詢來獲取et表中每個日期之前或之前的最近日期。其餘的只是加入了select子句的正確信息。

2

我就是這麼做的:

http://sqlfiddle.com/#!3/1c73b/5

select fname, etdate, 'eligible' as eligible 
from st 
where etdate between 
(select max(etdate) from et where status ='Eg') 
and 
(select max(etdate) from et where status ='In') 
union 
select fname, etdate, 'ineligible' as eligible 
from st 
where etdate not between 
(select max(etdate) from et where status ='Eg') 
and 
(select max(etdate) from et where status ='In') 
order by 2 
+0

使用聯盟所有,因爲你不會有愚蠢。也不確定這是否正確 - 你只是看最後的In/Eg行。如果你有1/10/12的etdate,他們將是「不合格」 - 即使1/10的有效記錄是「合格的」。 –

2

apply是專爲這一點。

select 
    ST.fName, stETD = ST.etDate, previousET.* 
from 
    ST 
    outer apply (
     select top 1 
      ET.Status, 
      ET.ETDate 
     from 
      ET 
     where 
      ET.ETDate <= ST.etDate 
     order by 
      ET.ETDate desc 
    ) previousET 
order by 
    2 

http://sqlfiddle.com/#!3/1c73b/11

這將讓你最近(order by ETDate desc)訴訟記錄(where ETDate <= ST.Date)。感謝mikeY爲小提琴。

+0

如果清理列名稱,那在我的小提琴中起作用。很酷。 – mikeY

+0

+1爲清楚起見,但我通常不喜歡相關的子查詢(這基本上是適用的歸結) –