【发布时间】:2021-01-14 08:22:56
【问题描述】:
花了一段时间找到最佳的为什么做这项工作后,我以这个查询结束,我只是想知道它是否按我预期的那样工作?经验表明 MySQL 总是给我一个惊喜,告诉我我的查询结构错误或没有达到预期的效率。
这是查询:
select
`users`.*,
`i`.`name` as `identity_name`,
`i`.`id` as `identity_id`,
`i`.`is_verified`
from
`users`
left join `identities` as `i` on `i`.`user_id` = `users`.`id`
and `i`.`id` = (
select
`i2`.`id`
from
`identities` as `i2`
where
`i2`.`user_id` = `i`.`user_id`
order by
`i2`.`is_verified` desc,
`i2`.`updated_at` desc
limit
1
)
用户表:
+---+-------------------+
| id| other columns ... |
+---+-------------------+
| 1 | user data ... |
| 2 | user data ... |
| 3 | user data ... |
| 4 | user data ... |
|...| user data ... |
+---+-------------------+
身份表:
+----+---------+-------------+-------------+-----------+
| id | user_id | is_verified | name | updated_at|
+----+---------+-------------+-------------+-----------+
| 1 | 1 | 0 | some name | 2001 |
| 2 | 1 | 1 | some name | 2000 |
| 3 | 2 | 0 | some name | 2000 |
| 4 | 1 | 0 | some name | 2000 |
| 5 | 3 | 1 | some name | 2003 |
|... | ... | ... | ......... | .... |
+----+---------+-------------+-------------+-----------+
预期输出:每个用户都应该有一个来自身份表的身份。 is_verified = 1 然后更新的 updated_at 的身份具有更高的优先级
很明显,id = 1 的用户是有问题的用户。
【问题讨论】:
-
您的代码不会严格返回 is_verified = 1 的行。还有为什么 id=1 的用户有问题?
-
因为 id=1 在 identities 表中有许多不同的行,并且应该只选择其中一个...我的主要目的是选择具有优先级的行,并且我希望每个用户都有身份(如果有的话)即使是强硬用户的身份也不是(is_verified = 1)
-
那我猜你的代码没问题,除非你的 MySql 版本是 8.0+,在这种情况下你可以使用窗口函数。
-
请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 暂停总体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。
-
@newmoon:您的代码很好——或者如果您运行的是 MySQL 8,您可以使用 forpas 演示的窗口函数(尽管它不一定会更快)。考虑在
identities(user_id, is_verified desc, updated_at desc, id)上建立索引以提高性能。
标签: mysql mariadb left-join sql-order-by greatest-n-per-group