这是我前阵子自己遇到的一个问题。当时有一个表,表大致是长这样的:
GroupID SectionID CreatedTime TextValue ----------- ----------- ------------------------ ----------- 1 1 2007-07-10 00:00:00.000 1-1-07-10 1 1 2007-07-11 00:00:00.000 1-1-07/11 1 2 2007-07-05 00:00:00.000 1-2-07/05 1 2 2007-07-11 00:00:00.000 1-2-07-11 1 3 2007-07-13 00:00:00.000 1-3-07-13 2 1 2007-07-10 00:00:00.000 2-1-07-10 2 1 2007-07-11 00:00:00.000 2-1-07-11 2 4 2007-07-09 00:00:00.000 2-4-07-09
其中GroupID, SectionID和CreatedTime是联合主键。当时希望写一个简单的查询,不用CURSOR、不用临时表和临时表变量,希望能得到这样的查询结果:
GroupID SectionID CreatedTime TextValue ----------- ----------- -------------------------- --------- 2 4 2007-07-09 00:00:00.000 2-4-07-09 2 1 2007-07-11 00:00:00.000 2-1-07-11 1 3 2007-07-13 00:00:00.000 1-3-07-13 1 2 2007-07-11 00:00:00.000 1-2-07-11 1 1 2007-07-11 00:00:00.000 1-1-07/11
也就是说,对于每一种(GroupID, SectionID)的组合,取出最后插入的那行。当时一下子还真没想出来怎么写。后来才找到答案的。现在这个问题是我最近使用最多的面试题。
答案如下:
SELECT * FROM TableInterview AS t1 Where EXISTS ( SELECT MAX(CreatedTime) FROM TableInterview AS t2 GROUP BY GroupId, SectionId HAVING GroupId = t1.GroupId and SectionId = t1.SectionId and max(CreatedTime) = t1.CreatedTime )
好像也不算很难写的样子。
打印 | 张贴于 2007-08-13 16:54:00 | Tag:Dot NET

留言反馈
SELECT t1.*
FROM TableInterview AS t1,
(
SELECT GroupId, SectionId,MAX(CreatedTime) as maxCreatedTime
FROM TableInterview
GROUP BY GroupId, SectionId
) as b
where
t1.GroupId= b.GroupId
and t1.SectionId =b.SectionId
and t1.CreatedTime=b.maxCreatedTime
Select GroupID, SectionID, Max(CreatedTime),Max(TextValue) as CreatedTime From TableInterview Group by GroupID,SectionID
(GroupID Char(2),
SectionID Char(2),
CreatedTime datetime,
TextValue Varchar(20),
)
Insert TableInterview Select '1', '1', '2007-07-10 00:00:00.000', '1-1-07-10'
Union All Select '1', '1', '2007-07-11 00:00:00.000', '1-1-07/11'
Union All Select '1', '2', '2007-07-05 00:00:00.000', '1-2-07/05'
Union All Select '1', '2', '2007-07-11 00:00:00.000', '1-2-07-11'
Union All Select '1', '3', '2007-07-13 00:00:00.000', '1-3-07-13'
Union All Select '2', '1', '2007-07-10 00:00:00.000', '2-1-07-10'
Union All Select '2', '1', '2007-07-11 00:00:00.000', '2-1-07-11'
Union All Select '2', '4', '2007-07-09 00:00:00.000', '2-4-07-09'
GO
---------------------
select * from TableInterview t
where not exists
(select 1 from TableInterview
where GroupID=t.GroupID and SectionID = t.SectionID
and CreatedTime>t.CreatedTime)
order by GroupID desc,SectionID desc
这样也不是挺好的吗
可能更重要的是SQL的执行效率吧
系统怀疑您的评论内容为广告,或者评论文字太短,请检查后重试!
不用CURSOR、不用临时表写一个存储过程。可以对任意两个结构相同的表。进行数据比较。将数据不同的记录显示出来。数据不同指的是。A表有B表无,B表有A表无。或者主KEY相同但是其中一个字段不同的数据。
第二,你可以看看我前些时间在这里发的招聘帖子
>> 我一般是问是否理解non clustered index的leaf node的内容,还有join的实现方式。
太狠了,你们公司是不是开发数据库基础软件? 现在的应届生,能写出正确的SQL语句就不错了
Create Table TableInterview
(GroupID Char(2),
SectionID Char(2),
CreatedTime date,
TextValue Varchar(20)
)
insert into TableInterview
values ('1', '1', '2007-07-10', '1-1-07-10'),
('1', '1', '2007-07-11', '1-1-07/11'),
('1', '2', '2007-07-05', '1-2-07/05'),
('1', '2', '2007-07-11 ', '1-2-07-11'),
('1', '3', '2007-07-13', '1-3-07-13'),
('2', '1', '2007-07-10', '2-1-07-10'),
('2', '1', '2007-07-11', '2-1-07-11'),
('2', '4', '2007-07-09', '2-4-07-09')
select GroupID,SectionID,CreatedTime, TextValue
from
(select GroupID,SectionID,CreatedTime, TextValue,
row_number() over (partition by GroupID,SectionID order by CreatedTime desc) as rr
from TableInterview)
as t
where t.rr = 1
所以还是可读性最重要.
其实无须GROUP BY
分享一下老贴
一道褒贬不一的 SQL 考试题
http://blog.csdn.net/playyuer/archive/2002/12/12/2848.aspx
个人认为下面的语句最易直接理解,相当于直接翻译成sql
SELECT *
FROM TableInterview a
Where
CreatedTime =
(select max(CreatedTime)
from TableInterview
where groupid = a.groupid
and SectionID = a.SectionID
)
SELECT t1.*
FROM TableInterview t1
inner join
(
SELECT MAX(CreatedTime) as MTime,GroupId,SectionId
FROM TableInterview
GROUP BY GroupId, SectionId ) t2
on t2.GroupId = t1.GroupId
and t2.SectionId = t1.SectionId
and t2.MTime = t1.CreatedTime
BTW,这两种写法的性能没差别。
先按GroupID,SectionID GROUP BY一下取出CreatedTime最大的再和原表inner join下估计速度会更快点.
楼主确实不厚道,何必把自己写不出来的作为面试题呢?
感觉心态上有些问题,虽然这是很基本的SQL
SELECT t1.*
FROM TableInterview AS t1,
(
SELECT GroupId, SectionId,MAX(CreatedTime) as maxCreatedTime
FROM TableInterview
GROUP BY GroupId, SectionId
) as b
where
t1.GroupId= b.GroupId
and t1.SectionId =b.SectionId
and t1.CreatedTime=b.maxCreatedTime
这样似乎更好理解一点
Create Table TableInterview
(GroupID Char(2),
SectionID Char(2),
CreatedTime datetime,
TextValue Varchar(20),
)
Insert TableInterview Select '1', '1', '2007-07-10 00:00:00.000', '1-1-07-10'
Union All Select '1', '1', '2007-07-11 00:00:00.000', '1-1-07/11'
Union All Select '1', '2', '2007-07-05 00:00:00.000', '1-2-07/05'
Union All Select '1', '2', '2007-07-11 00:00:00.000', '1-2-07-11'
Union All Select '1', '3', '2007-07-13 00:00:00.000', '1-3-07-13'
Union All Select '2', '1', '2007-07-10 00:00:00.000', '2-1-07-10'
Union All Select '2', '1', '2007-07-11 00:00:00.000', '2-1-07-11'
Union All Select '2', '4', '2007-07-09 00:00:00.000', '2-4-07-09'
GO
--查詢
SELECT *
FROM TableInterview AS t1
Where EXISTS
(
SELECT MAX(CreatedTime)
FROM TableInterview AS t2
GROUP BY GroupId, SectionId
HAVING GroupId = t1.GroupId
and SectionId = t1.SectionId
and max(CreatedTime) = t1.CreatedTime
)
GO
--刪除測試環境
Drop Table TableInterview
GO