如何通过最多一列获取SQL行,按另一列进行分组

时间:2012-01-19 14:34:05

标签: sql sql-server-2008 group-by max greatest-n-per-group

我需要读取旧数据库中的用户以用于新系统中的统计信息,但我没有原始用户表。但是,有一个统计表,其中包含每年的总和,我还可以在其中找到所有需要的用户信息。此外,这也只给了我活跃的用户,这就是我需要的。

该表包含以下相关列:(统计信息列与此处无关)

  • 用户ID
  • 名字
  • 电子邮件

我希望UserID是不同的,因此它是GROUP BY中唯一可以拥有的列。 我将在年份运行MAX,以获得最近一年的价值。 FirstName,LastName和Email需要与MAX(Year)的行相同。换句话说,这些年来人们可能已经改变了姓名和电子邮件,我只想要最后一个,因为它是唯一相关的。

我对SQL查询的最佳建议如下:

SELECT UserID, Firstname, LastName, Email, MAX(Year) AS Year
FROM myTable
GROUP BY UserID
ORDER BY LastName, FirstName

唯一的问题是SQL Server 2008不会让我这样做,因为所有列都必须使用MAX之类的函数或GROUP BY的一部分。 FirstName,LastName和Email列不能在GROUP BY下,因为这会产生太多记录。似乎某种方式将MAX放在所有这些上,但是我无法知道MAX函数实际上在哪一列。我不确定这会是一个问题,但我没有时间查看10万行,看看是否确实存在问题。

所以简而言之,我想要整行的五列,其中MAX只在一列上工作,GROUP BY在另一列上。有没有人有一个好的解决方案,或者在所有非分组行上使用MAX实际上是否安全?

2 个答案:

答案 0 :(得分:14)

一些答案​​......


相关的子查询...

SELECT
  *
FROM
  myTable
WHERE
  Year = (SELECT MAX(Year) FROM myTable AS lookup WHERE lookup.UserID = myTable.UserID)


加入派生汇总......

SELECT
  *
FROM
  myTable
INNER JOIN
  (SELECT UserID, MAX(Year) AS Year FROM myTable GROUP BY UserID) AS lookup
    ON  lookup.UserID = myTable.UserID
    AND lookup.Year   = myTable.Year


使用ROW_NUMBER()...

订购CTE
WITH
  sequenced_data AS
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY Year DESC) AS sequence_id,
    *
  FROM
    myTable
)
SELECT
  *
FROM
  sequenced_data
WHERE
  sequence_id = 1

答案 1 :(得分:3)

你是否每个用户只有一年的记录?如果是,那么你可以使用old'n'good join:

SELECT m.UserID, m.Firstname, m.LastName, m.Email, m.Year
FROM myTable m
    INNER JOIN (
        SELECT UserID, MAX(Year) as Year
        FROM myTable
        GROUP BY UserID
    ) x ON x.UserID=m.UserID and x.Year=m.Year
ORDER BY m.LastName, m.FirstName

当然你可以使用较新的SQL版本的构造,我只是习惯了较旧(=更通用)的可能性:)。