SQL Full Outer Join

时间:2011-11-26 01:36:35

标签: sql sql-server-2005 tsql outer-join

我有一个名为'Logs'的表,其中包含以下值:

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

问题是我无法在没有CheckIns的情况下生成日志:

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

某些优化器不支持sql的“FULL OUTER JOIN” 所以, 查询应该是:

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