SQL полное внешнее соединение - PullRequest
1 голос
/ 26 ноября 2011

У меня есть таблица с именем «Журналы» со следующими значениями:

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

Последовательность сопряжения CheckOut и 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 ]

5 голосов
/ 26 ноября 2011

Это должно работать:

;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.

Попробуйте рабочую демонстрацию для data.SE .

0 голосов
/ 26 ноября 2011

Некоторые из оптимизаторов не поддерживают "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
...