我所拥有的基本上是一个可以用多个表轻松解决的问题,但是我只有一个表可以解决。
考虑以下数据库表
UserID UserName EmailAddress Source 3K3S9 Ben ben@myisp.com user SF13F Harry lharry_x@hotbail.com 3rd_party SF13F Harry reside@domain.com user 76DSA Lisa cake@insider.com user OL39F Nick stick@whatever.com 3rd_party 8F66S Stan myman@lol.com user
我需要选择所有字段,但只需选择每个用户一次以及他们的电子邮件地址之一(由MAX()函数确定的“最大”地址)。这是我追求的结果…
UserID UserName EmailAddress Source 3K3S9 Ben ben@myisp.com user SF13F Harry lharry_x@hotbail.com 3rd_party 76DSA Lisa cake@insider.com user OL39F Nick stick@whatever.com 3rd_party 8F66S Stan myman@lol.com user
如您所见,“哈利”仅以其“最高”电子邮件地址显示一次,并带有相应的“来源”
当前正在发生的事情是,我们正在对UserID,UserName进行分组,并对EmailAddress和Source使用MAX(),但是这两个字段的最大值并不总是匹配,它们必须来自同一记录。
我通过将表与自身连接在一起尝试了另一个过程,但是我仅设法获得了正确的电子邮件地址,而没有获得该地址的相应“来源”。
任何帮助将不胜感激,因为我已经花了太长时间尝试解决此问题:)
如果您使用的是SQL Server 2005或更高版本,
SELECT UserID, UserName, EmailAddress, Source FROM (SELECT UserID, UserName, EmailAddress, Source, ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY EmailAddress DESC) AS RowNumber FROM MyTable) AS a WHERE a.RowNumber = 1
当然,有一些方法可以执行不具有(SQL-Standard)排名功能的相同任务,例如ROW_NUMBERSQL Server自2005年以来才实施- 包括嵌套的依赖查询和带有ON“>”和WHERE ... IS NULL技巧的自我左联接- -但是排名函数使代码易于阅读,并且在理论上可以被SQL Server Engine很好地优化。
ROW_NUMBER
ON
WHERE ... IS NULL
编辑:本文是有关排名的不错的教程,但是它RANK在示例中使用了而不是ROW_NUMBER(或其他排名函数DENSE_RANK)-当根据排序条件在同一分区中的分组行之间存在“联系”时,区别很重要。这篇文章很好地解释了差异。
RANK
DENSE_RANK