繁体   English   中英

第一顺序......那么GROUP BY

[英]FIRST ORDER BY … THEN GROUP BY

我有两个表,一个存储用户,另一个存储用户的电子邮件地址。

  • 表用户:( userIdusername etc
  • table userEmail:( emailIduserIdemail

我想做一个查询,允许我获取最新的电子邮件地址和用户记录。
我基本上是在寻找一个查询

FIRST ORDER BY userEmail.emailId DESC 
THEN GROUP BY userEmail.userId

这可以通过以下方式完成:

SELECT 
  users.userId
, users.username
, (
     SELECT 
       userEmail.email
     FROM userEmail
     WHERE userEmail.userId = users.userId
     ORDER BY userEmail.emailId DESC
     LIMIT 1
  ) AS email
FROM users
ORDER BY users.username;

但是这会为每一行做一个子查询,效率非常低。 (在我的程序逻辑中,做两个单独的查询并将它们“加入”在一起会更快。


为我想要的东西写的直观查询将是:

SELECT 
  users.userId
, users.username
, userEmail.email
FROM users
LEFT JOIN userEmail USING(userId)
GROUP BY users.userId
ORDER BY 
  userEmail.emailId
, users.username;

但是,这不符合我的意愿。 GROUP BY在排序之前执行,因此ORDER BY userEmail.emailId无需执行任何操作)。


所以我的问题是:
是否可以在不使用子查询的情况下编写第一个查询?


我已经搜索并阅读了有关stackoverflow的其他问题,但似乎没有人回答有关此查询模式的问题。

但是这会为每一行做一个子查询,效率非常低

首先,你有一个证明这个的查询计划/时间表吗? 你完成它的方式(使用subselect)几乎是“直观”的方式。 许多DBMS(虽然我不确定MySQL)对这种情况有优化,并且只能执行一次查询。

或者,您应该能够创建一个仅具有ONLY (user id, latest email id)元组的子表,并JOIN到该表:

SELECT 
  users.userId
, users.username
, userEmail.email
FROM users
INNER JOIN 
      (SELECT userId, MAX(emailId) AS latestEmailId
       FROM userEmail GROUP BY userId)
      AS latestEmails
      ON (users.userId = latestEmails.userId)
INNER JOIN userEmail ON
      (latestEmails.latestEmailId = userEmail.emailId)
ORDER BY users.username;

如果这是您经常进行的查询,我建议您优化表来处理此问题。

我建议在users表中添加emailId列。 当用户更改其电子邮件地址或将旧电子邮件地址设置为主电子邮件地址时,请更新users表中的users行以指示当前的emailId

修改代码以执行此更新后,您可以返回并更新旧数据以为所有用户设置emailId

或者,您可以向users表添加email列,这样您就不必进行联接即可获取用户当前的电子邮件地址。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM