屋顶上的木帷幕

海鸥之所以追着渔船飞,是因为它们认为会有沙丁鱼抛向大海 - Eric Cantona, 1995
随笔 - 146, 评论 - 3169, 引用 - 56

导航

关于


标签

每月存档

最新留言

广告

 

这是我前阵子自己遇到的一个问题。当时有一个表,表大致是长这样的:

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

留言反馈

#回复: 一个不算很难写的查询语句 编辑
个人感觉凭借元组关系演算转化,好像不是很难啊。无非就是寻找前两个项相同,但第三个数最大的行嘛。不知为什么你没用order by 子句
2008-01-22 19:32:00 | [匿名:Flashboy]
#回复: 一个不算很难写的查询语句 编辑
这是最好的写法 ,其他可读性很差
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
2007-10-26 14:20:00 | [匿名:boji]
#回复: 一个不算很难写的查询语句 编辑
面试通过不通过,并不完全取决于是否解答出问题。这是需要讲清楚的。
2007-10-23 10:43:00 | [匿名:mvm]
#回复: 一个不算很难写的查询语句 编辑
不知道這道題目是不是這位高手的得意之作.....
2007-09-28 10:54:00 | [匿名:kkkk]
#回复: 一个不算很难写的查询语句 编辑
是的,我的答案错了,需要子查询。
2007-09-20 17:34:00 | [匿名:Root]
#回复: 一个不算很难写的查询语句 编辑
是的,我的答案错了
2007-09-20 17:33:00 | [匿名:Root]
#回复: 一个不算很难写的查询语句 编辑
ROOT 兄弟,如果你参加这个面试的话,可能就挂了。
2007-09-05 16:55:00 | [匿名:查询语句]
#回复: 一个不算很难写的查询语句 编辑
Select GroupID, SectionID, Max(CreatedTime), Max(TextValue) From TableInterview Group by GroupID,SectionID
2007-08-31 23:34:00 | [匿名:root]
#回复: 一个不算很难写的查询语句 编辑
仔细想想,真的需要子查询吗?

Select GroupID, SectionID, Max(CreatedTime),Max(TextValue) as CreatedTime From TableInterview Group by GroupID,SectionID
2007-08-31 23:33:00 | [匿名:root]
#回复: 一个不算很难写的查询语句 编辑
难不倒。
2007-08-25 00:20:00 | [匿名:jon]
#回复: 一个不算很难写的查询语句 编辑
<script>
2007-08-21 23:15:00 | [匿名:<script>]
#回复: 一个不算很难写的查询语句 编辑
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 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

这样也不是挺好的吗
2007-08-21 17:10:00 | [匿名:与时俱进]
#回复: 一个不算很难写的查询语句 编辑
被SQL搞得团团转 :)
可能更重要的是SQL的执行效率吧
2007-08-20 11:43:00 | [匿名:hellone]
#回复: 一个不算很难写的查询语句 编辑
4个月更新一次,就写了个query....离我看到过的某高人写的华丽丽的query还是有些差距……
2007-08-19 00:49:00 | [匿名:cat]
#回复: 一个不算很难写的查询语句 编辑
是很简单啊,怎么会写不出来呢?呵呵
2007-08-17 20:31:00 | [匿名:easy]
#回复: 一个不算很难写的查询语句 编辑
这题目也够狠的。
系统怀疑您的评论内容为广告,或者评论文字太短,请检查后重试!
2007-08-16 16:35:00 | [匿名:怡红公子]
#回复: 一个不算很难写的查询语句 编辑
这题目也够狠的
2007-08-16 16:34:00 | [匿名:怡红公子]
#回复: 一个不算很难写的查询语句 编辑
我的面试题目
不用CURSOR、不用临时表写一个存储过程。可以对任意两个结构相同的表。进行数据比较。将数据不同的记录显示出来。数据不同指的是。A表有B表无,B表有A表无。或者主KEY相同但是其中一个字段不同的数据。
2007-08-16 14:09:00 | [匿名:悠自]
#回复: 一个不算很难写的查询语句 编辑
第一,俺不招应届生
第二,你可以看看我前些时间在这里发的招聘帖子
2007-08-16 10:06:00 | [匿名:怡红公子]
#回复: 一个不算很难写的查询语句 编辑
>> 怡红公子
>> 我一般是问是否理解non clustered index的leaf node的内容,还有join的实现方式。

太狠了,你们公司是不是开发数据库基础软件? 现在的应届生,能写出正确的SQL语句就不错了
2007-08-15 20:23:00 | [匿名:随便看看]
#回复: 一个不算很难写的查询语句 编辑
DB2用法
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
2007-08-15 17:10:00 | [匿名:xwing]
#回复: 一个不算很难写的查询语句 编辑
我一般是问是否理解non clustered index的leaf node的内容,还有join的实现方式。
2007-08-15 15:28:00 | [匿名:怡红公子]
#回复: 一个不算很难写的查询语句 编辑
不管你是否写group by,执行计划是完全一致的.
所以还是可读性最重要.
2007-08-15 15:26:00 | [匿名:怡红公子]
#回复: 一个不算很难写的查询语句 编辑
如果你是在3-5分钟内想出来(脱离查询分析器)的。那么用做面试题可能可以。我觉得这个面试题用来考察思维,共同讨论,或稍加引导,看面试者是否很快做出比较妥。
2007-08-15 08:55:00 | [匿名:活靶子]
#回复: 一个不算很难写的查询语句 编辑
看似需要GROUP BY
其实无须GROUP BY
2007-08-15 08:03:00 | [匿名:Microshaoft]
#回复: 一个不算很难写的查询语句 编辑
双not exists 更难理解一些

分享一下老贴

一道褒贬不一的 SQL 考试题
http://blog.csdn.net/playyuer/archive/2002/12/12/2848.aspx
2007-08-15 07:51:00 | [匿名:playyuer]
#回复: 一个不算很难写的查询语句 编辑
典型的相关子查询
个人认为下面的语句最易直接理解,相当于直接翻译成sql

SELECT *
FROM TableInterview a
Where
CreatedTime =
(select max(CreatedTime)
from TableInterview
where groupid = a.groupid
and SectionID = a.SectionID
)
2007-08-15 07:44:00 | [匿名:Microshaoft]
#回复: 一个不算很难写的查询语句 编辑
两种写法在SQL 2000的执行效率是一样的,SQL都会先 group by得到 maxCreateTime
2007-08-14 21:09:00 | [匿名:随便看看]
#回复: 一个不算很难写的查询语句 编辑
这个不是随便看看的做法吗?
2007-08-14 18:53:00 | [匿名:sevenever]
#回复: 一个不算很难写的查询语句 编辑
自己改了一下,主要是EXISTS 不太好理解.
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
2007-08-14 17:19:00 | [匿名:棒子面儿粥]
#回复: 一个不算很难写的查询语句 编辑
建议不要再拿它当面试题了,要不人大家要拍砖了
2007-08-14 13:19:00 | [匿名:Rock.NET]
#回复: 一个不算很难写的查询语句 编辑
我也比较习惯随便看看的写法,这样可读性更好。

BTW,这两种写法的性能没差别。
2007-08-14 10:17:00 | [匿名:怡红公子]
#回复: 一个不算很难写的查询语句 编辑
我要是面试碰到这种题就好啦
2007-08-14 09:22:00 | [匿名:HolybooK]
#回复: 一个不算很难写的查询语句 编辑
其实有很多种写法的
先按GroupID,SectionID GROUP BY一下取出CreatedTime最大的再和原表inner join下估计速度会更快点.
楼主确实不厚道,何必把自己写不出来的作为面试题呢?
感觉心态上有些问题,虽然这是很基本的SQL
2007-08-14 08:58:00 | [匿名:zdnet]
#回复: 一个不算很难写的查询语句 编辑
把CreateTime作为联合主键之一就很有问题。。。
2007-08-14 08:39:00 | [匿名:ff]
#回复: 一个不算很难写的查询语句 编辑
你自己都想了半天,还用来面试,不妥吧,面试毕尽不是为了考倒人面试者的
2007-08-14 08:30:00 | [匿名:乱发吹风]
#回复: 一个不算很难写的查询语句 编辑
--查詢
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

这样似乎更好理解一点
2007-08-13 21:43:00 | [匿名:随便看看]
#回复: 一个不算很难写的查询语句 编辑
还好,你不用参加自己的面试,不然怕要不过关.
2007-08-13 19:29:00 | [匿名:deerchao]
#回复: 一个不算很难写的查询语句 编辑
--創建測試環境
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
2007-08-13 17:26:00 | [匿名:破曉之陽]
#回复: 一个不算很难写的查询语句 编辑
老实说,这个真的不算很难。但是,可能仅仅是读起来不那么难。对我来说就这样,写起来就难了。
2007-08-13 17:15:00 | [匿名:qianyao]
博客主人设置本博客不允许匿名用户发表言论,请登录后再试

Powered by: Joycode.MVC引擎 0.5.2.0