【问题标题】:MySQL - How to use a correlated subquery inside a JOINMySQL - 如何在 JOIN 中使用相关子查询
【发布时间】:2020-09-27 04:12:12
【问题描述】:

我有两张桌子,ObjectsEvents

Objects 的结构如下:

ID | Password
-------------
0  | aaaa
1  | bbbb

事件的结构如下:

Object | Date       | Type
--------------------------
0      | 2020-06-01 | 0
0      | 2020-06-02 | 1

我想要实现的是:对于每个 ID,获取最后一个关联的事件类型。在上面的示例中,对象0 将与1 相关联,因为12020-06-02 上最后一个事件的类型。此外,当一个对象没有任何事件时,将1 关联到它。

我尝试为每个对象排序事件,这样我就可以使用查询加入我的对象信息:

SELECT ID, IFNULL(e.Type, 1)
FROM objects o
LEFT JOIN (
    SELECT e.Object, e.Date, e.Type
    FROM events e
    WHERE e.Object = o.ID
    ORDER BY e.Date DESC
    LIMIT 1
) AS e ON e.Object = o.ID

由于o.ID 未知,它不起作用,但我真的想不出任何其他解决方案。因此我的问题是:如何在连接表的条件内使用外部表的属性?

如果有不清楚的地方请告诉我,谢谢。

【问题讨论】:

  • 您对此样本数据的预期输出是什么?
  • 我只需要 ID 和类型。这就是我使用SELECT ID, IFNULL(e.Type, 1)的原因。

标签: mysql join greatest-n-per-group correlated-subquery


【解决方案1】:
SELECT ID, IFNULL(e.Type, 1)
FROM objects o
LEFT JOIN (
    SELECT e.Object, max(e.Date), e.Type
    FROM events e
    GROUP BY e.Date DESC
) AS e ON e.Object = o.ID

【讨论】:

  • 不,因为这只会返回加入其对象信息的最新事件,而我需要每个对象的最新事件。
  • 啊,现在我明白了。然后您需要聚合子查询中的行。类似于修改后的答案
【解决方案2】:

你可以试试这样的:

SELECT o.id, max(e.date) AS date, e.type
FROM objects o
INNER JOIN events e ON(o.id = e.object)
GROUP BY o.id, e.type
ORDER BY e.date DESC;

输出

+------+------------+------+
| id   | date       | type |
+------+------------+------+
|    0 | 2020-06-02 |    1 |
|    0 | 2020-06-01 |    0 |
+------+------------+------+

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    Events 中使用NOT EXISTS 仅返回按日期的最后一行:

    SELECT ID, IFNULL(e.Type, 1) Type
    FROM Objects o
    LEFT JOIN (
        SELECT e.Object, e.Type
        FROM Events e
        WHERE NOT EXISTS (
          SELECT 1 FROM Events
          WHERE Object = e.Object AND Date > e.Date 
        ) 
    ) AS e ON e.Object = o.ID
    

    或:

    SELECT 
      o.ID, 
      IFNULL((SELECT e.Type FROM Events e WHERE e.Object = o.ID ORDER BY e.Date DESC LIMIT 1), 1) Type
    FROM Objects o
    

    请参阅demo
    结果:

    > ID | Type
    > -: | ---:
    >  0 |    1
    >  1 |    1
    

    【讨论】:

      【解决方案4】:

      如果您有版本 8 或更高版本,您可以使用 row_number() 函数计算最后一行

      select * from
      (
      select id,coalesce(type,1) type,coalesce(date,date(now())) as dt,
               row_number() over (partition by o.id order by coalesce(date,date(now())) desc) rn
      from  objects o
      left join events e on e.object = o.id
      order by o.id,dt desc
      ) s
      where rn = 1;
      

      【讨论】:

        猜你喜欢
        • 2010-10-06
        • 2018-05-26
        • 2015-03-04
        • 1970-01-01
        • 2017-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-24
        相关资源
        最近更新 更多