【问题标题】:SELECT and JOIN to return only one row for each employeeSELECT 和 JOIN 只为每个员工返回一行
【发布时间】:2020-07-10 09:35:12
【问题描述】:

我有一个用户表,其中存储了employeeId、lastName、firstName、department、hire date 和 mostRecentLogin。

我有另一个存储员工 ID、电子邮件地址的表。

如果员工有多个电子邮件地址,则 emailAddress 表可以有多个行。

我正在尝试返回只为每位员工显示一行的结果。我不在乎哪个电子邮件地址,只要它只选择一个即可。

但我尝试过的所有查询总是返回所有可能的行。

这是我最近的尝试:

select *
from EmployeeInfo i
left join EmployeeEmail e ON i.employeeId = e.employeeId
where i.hireDate = 2015 
and employeeId IN (
    SELECT MIN(employeeId)
    FROM EmployeeInfo
    GROUP BY employeeId
)

但话又说回来,这会返回所有可能的行。

有没有办法让它工作?

【问题讨论】:

  • 你可以LEFT JOIN (SELECT TOP 1 email....) x ON x.employeeId = userTable.employeeId

标签: sql sql-server sql-server-2012 sql-server-2014


【解决方案1】:

使用子查询而不是连接:

select *
  , (select top 1 E.EmailAddress from EmplyeeEmail E where E.employeeId = I.employeeId)
from EmployeeInfo I
where I.hireDate = 2015;

注意:如果您改变主意并决定您确实偏好返回哪个电子邮件地址,那么只需在子查询中添加 order by - 否则真的不知道您会得到哪个。

【讨论】:

  • 好吧,如果没有ORDER BY 继续,那么您将获得的哪一个 行相当随意。如果这对你来说没问题 - 很好 - 但通常你想要一个 specific 行(第一行,最后一个 - 按可能的顺序排序),这只有在你提供 ORDER BY 子句时才有效
  • @marc_s 肯定 - 不过不会说那很危险吗? OP 说:“我不在乎哪个电子邮件地址,只要它只选择一个即可。” - 所以我相信他们的话 :) 但是是的,我自己永远不会那样做。
  • 很危险,因为许多人会期望某种“默认”排序——这在我所知道的任何 RDBMS 中都不存在。所以它最终可能会返回一个意外(并且可能是“错误”的结果) - 但你是对的,只要返回哪一行并不重要,那么你的代码就可以了
  • @marc_s 你会通过 E.EmailAddress 订购吗?谢谢
  • @SkyeBoniwell:按您认为有意义的方式订购 - 电子邮件地址、名字、姓氏、鞋码 - 无论您的系统需要什么......
【解决方案2】:

这应该可行。

SELECT *
FROM EmployeeInfo
Left JOIN EmployeeEmail
  ON EmployeeInfo.employeeId = EmployeeEmail.employeeId
WHERE EmployeeInfo.hireDate = '2015'
GROUP BY EmployeeInfo.employeeId;

【讨论】:

  • 这在 SQL Server 上不起作用,因为您尝试选择 *,但只能按 employeeId 分组。
  • @DaleK 哦,很有趣。但我想既然 EmployeeInfo.employee.Id 列有重复的数据值,我们就可以在这里分组?
  • 首先,我严重怀疑 EmployeeInfo 表中是否存在重复的employeeId,重复项在 EmployeeEmail 表中。其次,您只能选择分组依据或聚合依据的列,因此您必须将 select * 更改为 select EmployeeId
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多