2011-11-26 94 views
1

我有一個名爲「日誌」使用下面的值表:SQL全外連接

CheckDate  CheckType  CheckTime 
------------------------------------------- 
2011-11-25  IN    14:40:00 
2011-11-25  OUT    14:45:00 
2011-11-25  IN    14:50:00 
2011-11-25  OUT    14:55:00 
2011-11-25  IN    15:00:00 
2011-11-25  OUT    15:05:00 
2011-11-25  IN    15:15:00 
2011-11-25  OUT    15:20:00 
2011-11-25  IN    15:25:00 
2011-11-25  OUT    15:30:00 
2011-11-25  OUT    15:40:00 
2011-11-25  IN    15:45:00 

我想使用上表產生的結果是:

CheckDate  CheckIn  CheckOut 
----------------------------------------- 
2011-11-25  14:40:00  14:45:00 
2011-11-25  14:50:00  14:55:00 
2011-11-25  15:00:00  15:05:00 
2011-11-25  15:15:00  15:20:00 
2011-11-25  15:25:00  15:30:00 
2011-11-25  NULL   15:40:00 
2011-11-25  15:45:00  NULL 

到目前爲止,我已經提出了這樣的結果集:

CheckDate  CheckIn  CheckOut 
----------------------------------------- 
2011-11-25  14:40:00  14:45:00 
2011-11-25  14:50:00  14:55:00 
2011-11-25  15:00:00  15:05:00 
2011-11-25  15:15:00  15:20:00 
2011-11-25  15:25:00  15:30:00 
2011-11-25  15:45:00  NULL 

的問題是我不能沒有簽入生成日誌:

CheckDate  CheckIn  CheckOut 
----------------------------------------- 
2011-11-25  NULL   15:40:00 

CheckIn - CheckOut配對和順序的順序在增加時間值。

編輯:這是我當前的查詢

SELECT Ins.CheckDate, 
     Ins.CheckTime, 
     Outs.CheckTime 

    FROM (SELECT CheckDate, 
       CheckTime 
      FROM Logs 
     WHERE CheckType = 'I') Ins 

    FULL OUTER JOIN 

     (SELECT CheckDate, 
       CheckTime 
      FROM Logs 
     WHERE CheckType = 'O') Outs 

    ON Ins.CheckDate = Outs.CheckDate AND 
     Ins.CheckTime < Outs.CheckTime 
+3

「到目前爲止,我已經想出這個結果集」:你能分享SQL的呢? – Thilo

+0

你可以發佈你給出結果的查詢嗎? –

+0

這是日誌表的全部範圍還是每個條目有其他一些關鍵字?你可以包含你用來生成當前結果集的SQL嗎? –

回答

5

這應該工作:

;WITH x AS (
    SELECT CheckDate, CheckType, CheckTime 
     ,row_number() OVER (ORDER BY CheckDate, CheckTime) As rn 
    FROM #t 
) 
SELECT CASE WHEN x.CheckType = 'IN' OR x.rn = 1 THEN x.CheckDate 
               ELSE y.CheckDate END AS CheckDate 
     ,CASE WHEN x.CheckType = 'IN' THEN x.CheckTime ELSE NULL END AS CheckIn 
     ,CASE WHEN y.CheckType = 'OUT' THEN y.CheckTime 
      WHEN x.CheckType = 'OUT' THEN x.CheckTime ELSE NULL END AS CheckOut 
FROM x 
LEFT JOIN x AS y ON y.rn = x.rn + 1 
WHERE x.CheckType = 'IN' 
OR  y.CheckType = 'OUT' 
OR  x.rn = 1 

它產生完全相同的輸出要求,涵蓋特殊情況下

  • OUT後跟另一個OUT(缺少IN
  • IN後跟其他IN(缺少OUT
  • IN後面是什麼(最後一行)。
  • 第一行以OUT開頭。

嘗試working demo on data.SE

+0

不錯的解決方案。簡單而高效。 –

+1

+1工作演示! – Bert

+0

@JustinGrant:謝謝,但實際上,如果它以'OUT'開頭,第一行就會丟失。這不是問題,而是科學!現在也包括在內。在'CheckOut'的CASE語句中從'y.CheckType'切換到'x.CheckType'是在這種情況下保持簡單和高效的一種特殊方式。 :) –

0

一些優化器不支持「FULL OUTER JOIN」 SQL 所以, 查詢應該是:

SELECT Ins.CheckDate, 
     Ins.CheckTime, 
     Outs.CheckTime 

    FROM (SELECT CheckDate, 
       CheckTime 
      FROM Logs 
     WHERE CheckType = 'I') Ins 

    LEFT OUTER JOIN 

     (SELECT CheckDate, 
       CheckTime 
      FROM Logs 
     WHERE CheckType = 'O') Outs 

    ON Ins.CheckDate = Outs.CheckDate AND 
     Ins.CheckTime < Outs.CheckTime 

UNION 

SELECT Ins.CheckDate, 
     Ins.CheckTime, 
     Outs.CheckTime 

    FROM (SELECT CheckDate, 
       CheckTime 
      FROM Logs 
     WHERE CheckType = 'I') Ins 

    RIGHT OUTER JOIN 

     (SELECT CheckDate, 
       CheckTime 
      FROM Logs 
     WHERE CheckType = 'O') Outs 

    ON Ins.CheckDate = Outs.CheckDate AND 
     Ins.CheckTime < Outs.CheckTime