如何在 MySQL 5.7 中执行相当于横向连接的操作?

How to do the equivalent of a lateral join in MySQL 5.7?

我正在尝试从两个 table 中获取信息,一个 table 包含关于对象 A 的一般数据,而 B 保存该对象的补充数据的历史记录。

我想做的是通过快速请求从 A 和 B 的相应最新实例(最高 id)获取所有记录,这两个 table 相当大。 B 有一个密钥,允许它识别它链接到哪个 A,因为它是一对多关系。 如果有来自第三个 table C 的信息,我也想获取信息,我可以从 B 中存在的两个字段获取这些信息。给定的 B 也可能没有 C 数据,我想知道那也是..

根据我在论坛上搜索到的内容,横向连接似乎是解决方案,但它在我的 MySQL 版本中不存在。

我还希望能够使用 A 和 B 列值中的可变条件过滤查询。

我现在正在尝试的(功能正常,如果我可以等几个小时)是:

SELECT a.*, b.*, c.* 
FROM a
    INNER JOIN (SELECT b.* FROM b ORDER BY b.id DESC) b ON b.a_id = a.id
    LEFT JOIN c ON c.val1 = b.val1 AND c.val2 = b.val2
GROUP BY b.id

您所描述的是 window 功能,如 ROW_NUMBER() 帮助,但那些也是 MySQL 8+。对于 MySQL 5.7,事情有点棘手,但有几种方法可以做到。

SET @rank := 0;
SET @aid := 0;

SELECT
  a.*, b.*, c.*
FROM
  a
INNER JOIN (
    SELECT
      @rank := CASE WHEN b.a_id = @aid THEN @rank + 1 ELSE 1 END AS RankedRow
      ,b.*
      ,@aid := b.a_id
    FROM
      b
    ORDER BY
      b.a_id
      ,b.id DESC
) AS b
  ON a.id = b.a_id
  AND b.RankedRow = 1
LEFT JOIN c
  ON c.val1 = b.val1
  AND c.val2 = b.val2

这使用一个变量来保存当前行号,并使用一个技巧来更新该值以及 return 它。如果 a_id 相同,它会增加 1,但当 a_id 改变时,它会重置为 1。

另一种选择是将 b 加入自身

SELECT
  a.*, b.*, c.*
FROM
  a
INNER JOIN (
  SELECT
    b.*
  FROM
    b
  LEFT JOIN b AS newerb
    ON newerb.a_id = b.a_id
    AND newerb.id > b.id
  WHERE
    newerb.id IS NULL
) AS b
  ON a.id = b.a_id
LEFT JOIN c
  ON c.val1 = b.val1
  AND c.val2 = b.val2

如果同一 a_id 没有大于 b 的 id,则 newerb 将为空,因此必须是最新的行。

我过去使用过这两种解决方案,我更喜欢后者,因为它更具可读性,但它可能会更慢,具体取决于您拥有的数据量。

我没有时间测试这两个示例,因此对于我遗漏的任何拼写错误提前表示歉意。