mysql - 如何在 MySQL 5.7 中进行相当于横向连接的操作?
问题描述
我正在尝试从两个表中获取信息,一个表包含有关对象 A 的一般数据,另一个表包含该对象的补充数据的历史记录。
我想要做的是从 A 中获取所有记录以及 B 的相应最新实例(最高 id),请求速度很快,两个表都很大。B 有一个密钥,允许它识别它链接到哪个 A,因为它是一对多关系。我还想从第三个表 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
解决方案
您的描述是像 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
这使用一个变量来保存当前行号,并使用一个技巧来更新该值并返回它。如果 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 将为空。
我过去使用过这两种解决方案,我更喜欢后者,因为它更具可读性,但根据您拥有的数据量,它可能会更慢。
我没有时间测试这两个例子,所以对于我错过的任何错别字提前道歉。
推荐阅读
- r - 使用 R 中的点和颜色为不同条件创建散点图
- java - 管理员更改用户密码后出现 IncorrectCredentialsException
- python - PyCharm 不强制从具有具体类型参数的通用抽象类继承
- node.js - 在 Node + Express API 中检测到的打开句柄会阻止 Jest 退出
- graphql - 文本字段与服务器的双向同步 - 快速输入
- flutter - 在 Flutter 中接收到 token 后导航到主屏幕
- ajax - Google 图表不会基于新的 Ajax 过滤器重绘图表
- google-cloud-functions - 您可以运行可从公共 ip 访问的 /host firebase 模拟器吗?
- javascript - 为什么这个函数不触发?
- python - 使用 FRIDA Stalker 制作的指令计数器