【问题标题】:Is there a way to limit a left outer join?有没有办法限制左外连接?
【发布时间】:2010-02-10 13:50:27
【问题描述】:

我有一个具有以下格式(和示例数据)的日志表:

  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。

谢谢。

【问题讨论】:

  • 我在ON 子句之后发现了一个缺失的WHERE
  • 我想你想让 'i' 中的一行与 'j' 中的下一行配对?从您的描述中看不太清楚。

标签: sql postgresql


【解决方案1】:

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

【讨论】:

  • @ijw 是的,'i' 和 'j' 基本上是同一张表。如果根据日期和时间对行进行排序,我希望一行与它之后的行配对
  • @Quassnoi 这是我第一次听说领先,如果我在“i”和“j”中除了日期和时间之外还有其他列,它也会起作用吗?
  • @absolute0:是的,它会的。在PostgreSQL中,您可以在一个字段中选择整条记录,然后在上层查询或客户端将其展开。
  • 很遗憾,我们使用的是 PostgreSQL 8.1,我会试试你的其他建议
  • PostgreSQl 8.3 及以下的建议不起作用,但一时兴起,我更改了原始 sql 的这一部分:“AND (j.date > i.date OR (j.date == i .date AND j.time > i.time))" 到您使用的语法中:"AND (j.date, j.time) > (i.date, i.time)" 并且由于某些原因,它像我一样工作希望它...我也是第一次遇到这种语法。谢谢!
【解决方案2】:
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

【讨论】:

    猜你喜欢
    • 2021-08-08
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    相关资源
    最近更新 更多