TSQL选择最大值

时间:2010-07-15 19:48:30

标签: tsql max

Userid   FirstName   LastName        UserUpdate 
1        Dan         Kramer          1/1/2005  
1        Dan         Kramer          1/1/2007  
1        Dan         Kramer          1/1/2009  
2        Pamella     Slattery        1/1/2005  
2        Pam         Slattery        1/1/2006  
2        Pam         Slattery        1/1/2008  
3        Samamantha  Cohen           1/1/2008  
3        Sam         Cohen           1/1/2009  

我需要为所有这些用户提取最新更新,基本上这就是我正在寻找的内容:

Userid   FirstName   LastName        UserUpdate  
1        Dan         Kramer          1/1/2009     
2        Pam         Slattery        1/1/2008   
3        Sam         Cohen           1/1/2009  

现在我运行以下内容:

SELECT Userid,FirstName,LastName,Max(UserUpdate)AS MaxDate 从表 GROUP BY Userid,FirstName,LastName

我仍然得到重复,如下:

Userid   FirstName   LastName        UserUpdate 
1        Dan         Kramer          1/1/2009  
2        Pamella     Slattery        1/1/2005  
2        Pam         Slattery        1/1/2008  
3        Samamantha  Cohen           1/1/2008  
3        Sam         Cohen           1/1/2009 

4 个答案:

答案 0 :(得分:4)

尝试:

declare @Table table (userid int,firstname varchar(10),lastname varchar(20), userupdate datetime)
INSERT @Table VALUES (1, 'Dan'         ,'Kramer'          ,'1/1/2005')  
INSERT @Table VALUES (1, 'Dan'         ,'Kramer'          ,'1/1/2007')  
INSERT @Table VALUES (1, 'Dan'         ,'Kramer'          ,'1/1/2009')  
INSERT @Table VALUES (2, 'Pamella'     ,'Slattery'        ,'1/1/2005')  
INSERT @Table VALUES (2, 'Pam'         ,'Slattery'        ,'1/1/2006')  
INSERT @Table VALUES (2, 'Pam'         ,'Slattery'        ,'1/1/2008')  
INSERT @Table VALUES (3, 'Samamantha'  ,'Cohen'           ,'1/1/2008')
INSERT @Table VALUES (3, 'Sam'         ,'Cohen'           ,'1/1/2009') 

SELECT
    dt.Userid,dt.MaxDate
        ,MIN(a.FirstName) AS FirstName, MIN(a.LastName) AS LastName
    FROM (SELECT 
              Userid, Max(UserUpdate) AS MaxDate 
              FROM @Table GROUP BY Userid
         ) dt
        INNER JOIN @Table a ON dt.Userid=a.Userid and dt.MaxDate =a.UserUpdate
    GROUP BY dt.Userid,dt.MaxDate

输出:

Userid      MaxDate                 FirstName  LastName
----------- ----------------------- ---------- --------------------
1           2009-01-01 00:00:00.000 Dan        Kramer
2           2008-01-01 00:00:00.000 Pam        Slattery
3           2009-01-01 00:00:00.000 Sam        Cohen

答案 1 :(得分:3)

你没有得到重复。从数据库的角度来看,'Pam'不等于'Pamella';事实上,一个是对另一个的口语缩短,这对数据库引擎没有任何意义。实际上没有可靠,通用的方法(因为有些名称有多个缩写,例如“Rob”或“Bob”用于“Robert”,以及缩写可以适合多个名称,如“Kel”代表“Kelly” “或”Kelsie“,让单独这个名称可以有替代拼写的事实。)

对于您的简单示例,您只需选择SUBSTRING(FirstName, 1, 3)而不是FirstName进行分组,但这只是基于您的示例数据的巧合;其他名称缩写不适合这种模式。

答案 2 :(得分:1)

或者使用子查询...

SELECT
   a.userID,
   a.FirstName,
   a.LastName,
   b.MaxDate
FROM
      myTable a
   INNER JOIN
      (   SELECT
             UserID,
             Max(ISNULL(UserUpdate,GETDATE())) as MaxDate
          FROM
             myTable
          GROUP BY
             UserID
      ) b
   ON
          a.UserID = b.UserID
      AND a.UserUpdate = b.MaxDate

子查询(名为“b”)返回以下内容:

Userid   UserUpdate  
1        1/1/2009     
2        1/1/2008   
3        1/1/2009 

子查询和原始表之间的INNER JOIN导致仅对原始表进行过滤以匹配记录 - 即,仅返回具有与子查询中的UserID / MaxDate对匹配的UserID / UserUpdate对的记录,为您提供您正在寻找的非重复结果集:

Userid   FirstName   LastName        UserUpdate  
1        Dan         Kramer          1/1/2009     
2        Pam         Slattery        1/1/2008   
3        Sam         Cohen           1/1/2009  

当然,这只是一种解决方法。如果你真的想长期解决这个问题,你应该将原始表格分成两部分来规范化。

表1:

Userid   FirstName   LastName 
1        Dan         Kramer   
2        Pam         Slattery 
3        Sam         Cohen

表2:

Userid   UserUpdate  
1        1/1/2007     
2        1/1/2007   
3        1/1/2007  
1        1/1/2008     
2        1/1/2008   
3        1/1/2008 
1        1/1/2009     
2        1/1/2009   
3        1/1/2009 

这将是一种更标准的数据存储方式,并且查询起来会更容易(无需借助子查询)。在这种情况下,查询将如下所示:

SELECT
   T1.UserID,
   T1.FirstName,
   T1.LastName,
   MAX(ISNULL(T2.UserUpdate,GETDATE()))
FROM
      Table1 T1
   LEFT JOIN
      Table2 T2
   ON
      T1.UserID = T2.UserID
GROUP BY
   T1.UserID,
   T1.FirstName,
   T1.LastName

答案 3 :(得分:0)

另一个替代方案,如果您有SQL 2005(我认为?)或更高版本将使用公用表表达式并从表中提取用户ID和最大日期然后加入,以获得匹配的名字和姓氏最大日期。注意 - 这假设userid + date始终是唯一的,如果获得具有相同用户ID和日期的2行,查询将中断。正如其他人已经指出的那样,这是非常糟糕的数据库设计 - 但有时候这就是生活,问题仍然必须解决。 e.g。

declare @Table table (userid int,firstname varchar(10),lastname varchar(20), userupdate datetime) 
INSERT @Table VALUES (1, 'Dan'         ,'Kramer'          ,'1/1/2005')   
INSERT @Table VALUES (1, 'Dan'         ,'Kramer'          ,'1/1/2007')   
INSERT @Table VALUES (1, 'Dan'         ,'Kramer'          ,'1/1/2009')   
INSERT @Table VALUES (2, 'Pamella'     ,'Slattery'        ,'1/1/2005')  
INSERT @Table VALUES (2, 'Pam'         ,'Slattery'        ,'1/1/2006')   
INSERT @Table VALUES (2, 'Pam'         ,'Slattery'        ,'1/1/2008')   
INSERT @Table VALUES (3, 'Samamantha'  ,'Cohen'           ,'1/1/2008') 
INSERT @Table VALUES (3, 'Sam'         ,'Cohen'           ,'1/1/2009'); 



with cte ( userid , maxdt ) as 
    (select userid, 
            max(userupdate) 
    from @table 
    group by userid)


SELECT  dt.Userid,
        dt.firstname,
        dt.lastname,
        cte.maxdt

FROM    
    @Table dt
    join cte on cte.userid = dt.userid and dt.userupdate = cte.maxdt

输出

Userid      firstname  lastname             maxdt
----------- ---------- -------------------- -----------------------
3           Sam        Cohen                2009-01-01 00:00:00.000
2           Pam        Slattery             2008-01-01 00:00:00.000
1           Dan        Kramer               2009-01-01 00:00:00.000