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
答案 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