小编典典

第一次订购-然后是GROUP BY

sql

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

  • 表用户:( ,userId,)username``etc
  • 表USEREMAIL:( , emailId,)userId``email

我想做一个查询,使我可以获取最新的电子邮件地址以及用户记录。
我基本上是在寻找一个说

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;

但这对每一行都执行子查询,并且效率很低。(执行2个单独的查询并将它们“联接”到我的程序逻辑中更快)。

编写我想要的内容的直观查询将是:

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的其他问题,但是似乎没有人回答有关此查询模式的问题。


阅读 278

收藏
2021-04-07

共1个答案

小编典典

但这对每一行都执行子查询,并且效率很低

首先,您是否有一个证明这一点的查询计划/时间安排?您完成操作的方式(使用子选择)几乎是执行操作的“直观”方式。许多DBMS(尽管我不确定MySQL)都针对这种情况进行了优化,并且将只能执行一次查询。

另外,您应该能够仅使用一个(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;
2021-04-07