Sql 第一批订单由。。。然后分组

Sql 第一批订单由。。。然后分组,sql,mysql,Sql,Mysql,我有两个表,一个存储用户,另一个存储用户的电子邮件地址 表用户:(userId,username,等) 表userEmail:(emailId,userId,email) 我想做一个查询,允许我获取最新的电子邮件地址以及用户记录。 我基本上是在寻找一个 FIRST ORDER BY userEmail.emailId DESC THEN GROUP BY userEmail.userId 这可以通过以下方式实现: SELECT users.userId , users.userna

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

  • 表用户:(
    userId
    username
  • 表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;
但这会对每一行执行子查询,效率非常低。(在我的程序逻辑中,执行两个单独的查询并将它们“连接”在一起会更快)


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

SELECT 
  users.userId
, users.username
, userEmail.email
FROM users
LEFT JOIN userEmail USING(userId)
GROUP BY users.userId
ORDER BY 
  userEmail.emailId
, users.username;
但是,这不是我想要的。(排序之前会执行
分组依据
,因此
按userEmail.emailId排序
与此无关)


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



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

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

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

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

或者,您可以将
电子邮件
列添加到
用户
表中,这样您就不必通过加入来获取用户的当前电子邮件地址

但这会对每一行执行子查询,效率非常低

首先,您是否有一个可以证明这一点的查询计划/时间安排?您所使用的方法(使用subselect)基本上是一种“直观”的方法。许多数据库管理系统(尽管我不确定MySQL)对此情况进行了优化,并且可以只执行一次查询

或者,您应该能够仅使用
(用户id、最新电子邮件id)
元组创建子表,并将
连接到该子表上:

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;

我可以问一下,您将电子邮件单独存储的动机是什么吗?您是否使用最新的emailId来指示用户的主要电子邮件地址是哪个电子邮件地址?这将阻止用户选择旧的电子邮件地址作为主地址。您是否考虑过只向用户表中添加一个emailId?当用户更改其电子邮件地址时,会添加新地址,旧电子邮件地址会保留一年,然后再被删除(根据规范),我想通过适当的表设计可以使查询更有效、更有意义。@NamshubWriter,我已经考虑过,但它会创建一个循环引用,我想阻止它。此外,我在其他情况下也有上述问题,因此我想了解一般情况下的最佳解决方案。