Есть ли способ ограничить левое внешнее соединение? - PullRequest
4 голосов
/ 10 февраля 2010

У меня есть таблица журнала в следующем формате (и пример данных):

  date     |  time
2010/01/02 | 10:00
2010/01/02 | 13:00
2010/01/04 | 02:34

Я хочу сделать запрос SQL, который будет получать результаты в следующем формате:

date1      | time1 | date2      | time2
2010/01/02 | 10:00 | 2010/01/02 | 13:00
2010/01/02 | 13:00 | 2010/01/04 | 02:34
2010/01/04 | 02:34 | <null>     | <null>

Так что я думал, что левое внешнее объединение сделает трюк:

SELECT
  i.date as date1,
  i.time as time1,
  j.date as date2,
  j.time as time2
FROM
  log_table i
  LEFT OUTER JOIN
    log_table j
  ON
    i.id = j.id
    AND (j.date > i.date
    OR (j.date == i.date AND j.time > i.time))

Однако это приведет к следующему:

date1      | time1 | date2      | time2
2010/01/02 | 10:00 | 2010/01/02 | 13:00
2010/01/02 | 10:00 | 2010/01/04 | 02:34
2010/01/02 | 13:00 | 2010/01/04 | 02:34
2010/01/04 | 02:34 | <null>     | <null>

Кстати, используемая база данных - PostgreSql.

Спасибо.

Ответы [ 2 ]

3 голосов
/ 10 февраля 2010

В PostgreSQL 8.4:

SELECT  date AS date1, time AS time1,
        LEAD(date) OVER (ORDER BY date, time, id) AS date2,
        LEAD(time) OVER (ORDER BY date, time, id) AS time2
FROM    log_table
ORDER BY
        date, time, id

, или просто так:

SELECT  date1, time1, (lnext).*
FROM    (
        SELECT  date AS date1, time AS time1,
                LEAD(lt) OVER (ORDER BY date, time, id) AS lnext
        FROM    log_table lt
        ) q
ORDER BY
        date, time, id

В PostgreSQL 8.3 и ниже:

SELECT  date AS date1, time AS time1,
        (li).date AS date2, (li).time AS time2
FROM    (
        SELECT  lo.*,
                (
                SELECT  li
                FROM    log_table li
                WHERE   (li.date, li.time, li.id) > (lo.date, lo.time, lo.id)
                ORDER BY
                        date, time, id
                LIMIT 1
                ) AS li
        FROM    log_table lo
        ) q
0 голосов
/ 10 февраля 2010
SELECT 
  i.date as date1, 
  i.time as time1, 
  min(j.date) as date2, 
  min(j.time) as time2 
FROM 
  log_table i 
  LEFT OUTER JOIN 
    log_table j 
  ON 
    i.id = j.id 
    AND (j.date > i.date 
    OR (j.date == i.date AND j.time > i.time)) 
GROUP BY i.date, i.time
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...