用Sql能解决这样的问题吗?

darwin77 2009-04-07 01:28:05
有一个游客使用游泳池纪录表:
Id BeginTime EndTime
1 2003-4-2 12:3:4 2003-4-2 12:3:4
2 2003-4-3 2:3:4 2003-4-12 2:3:4
3 2003-3-2 12:3:4 2003-4-2 12:3:4
4 2003-4-2 12:3:4 2003-5-2 12:3:4
5 2002-4-2 12:3:4 2003-4-2 5:3:4
6 2003-4-2 14:3:4 2009-4-2 17:3:4
.......(数据乱输入的,保证Begintime<EndTime就行了)
要得到:1 游泳池有人使用,但是同时使用人数最少的时间段;2 游泳池同时使用人数最多的时间段
注意:结构有可能是多个时间段。

3Q
...全文
92 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
darwin77 2009-04-07
  • 打赏
  • 举报
回复
打断的那部分语句巧妙极了,再次感谢。
ws_hgo 2009-04-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 darwin77 的回复:]
我晕!打断了再关联原表统计出现频率,是这个意思吧?
太天才了......

多谢多谢,万分感谢。。。。。。。。。
[/Quote]
看来理解啦
darwin77 2009-04-07
  • 打赏
  • 举报
回复
我晕!打断了再关联原表统计出现频率,是这个意思吧?
太天才了......

多谢多谢,万分感谢。。。。。。。。。
子陌红尘 2009-04-07
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 darwin77 的回复:]
子陌红尘(retired)的语句正在看,挺头大的,能说下思路吗?
[/Quote]

因为楼主原始表的每条记录都是在一个时间跨度范围内的,这个时间跨度或大或小。

而现在需要做的第一步就是把这些看似纷乱的时间跨度,细分成一个一个的时间段。

取时间段的方法很简单,把每个时间跨度的首尾时间都取出来,按照时间先后顺序排列,每两个相邻的时间就是一个最小粒度的时间段,见如下SQL:
    (select
a.BeginTime,min(b.EndTime) as EndTime
from
(select distinct BeginTime from @tab union all select distinct EndTime from @tab) a,
(select distinct EndTime from @tab union all select distinct BeginTime from @tab) b
where
a.BeginTime<b.EndTime
group by
a.BeginTime) m


取得了所有的时间段之后,处理起来就简单得多,只需要判断时间段是否完全存在于原始表记录的起始和截止时间之间,并依此为依据统计即可得到表变量中的记录。

最后一步从表变量中取数据,不需要说明了吧...
darwin77 2009-04-07
  • 打赏
  • 举报
回复
子陌红尘(retired)的语句正在看,挺头大的,能说下思路吗?
darwin77 2009-04-07
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 Zoezs 的回复:]
你的时间段应该能知道吧?
[/Quote]

时间段就是每人次使用纪录的开始到结束时间规定的那个时间段,
比如:
Id BeginTime EndTime
1 2003-4-2 12:3:4 2003-4-2 12:3:4
表示有一人次在2003-4-2 12:3:4到2003-4-2 12:3:4使用了游泳池。
子陌红尘 2009-04-07
  • 打赏
  • 举报
回复

--创建测试数据
declare @tab table(Id int,BeginTime datetime,EndTime datetime)
insert into @tab select 1,'2003-04-02 10:03:04','2003-4-02 13:03:04'
insert into @tab select 2,'2003-04-03 02:03:04','2003-4-03 03:03:04'
insert into @tab select 3,'2003-03-02 11:03:04','2003-4-02 13:03:04'
insert into @tab select 4,'2003-04-02 12:03:04','2003-4-02 13:03:04'
insert into @tab select 5,'2003-04-02 13:03:04','2003-4-02 15:03:04'
insert into @tab select 6,'2003-04-02 14:03:04','2009-4-02 17:03:04'

--建一个中间表,保存所有时段使用人数的统计数据
declare @rec table(BeginTime datetime,EndTime datetime,num int)

--生成统计数据并插入中间表
insert into @rec
select
m.BeginTime,m.EndTime,count(n.id) as num
from
(select
a.BeginTime,min(b.EndTime) as EndTime
from
(select distinct BeginTime from @tab union all select distinct EndTime from @tab) a,
(select distinct EndTime from @tab union all select distinct BeginTime from @tab) b
where
a.BeginTime<b.EndTime
group by
a.BeginTime) m left join @tab n
on
(m.BeginTime between n.BeginTime and n.EndTime)
and
(m.EndTime between n.BeginTime and n.EndTime)
group by
m.BeginTime,m.EndTime
having count(n.id)>0

--查询出所有使用人数最少的时段
select t.* from @rec t where not exists(select 1 from @rec where num<t.num)
/*
BeginTime EndTime num
------------------------------------------------------ ------------------------------------------------------ -----------
2003-03-02 11:03:04.000 2003-04-02 10:03:04.000 1
2003-04-02 13:03:04.000 2003-04-02 14:03:04.000 1
2003-04-02 15:03:04.000 2003-04-03 02:03:04.000 1
2003-04-03 03:03:04.000 2009-04-02 17:03:04.000 1
*/

--查询出所有使用人数最多的时段
select t.* from @rec t where not exists(select 1 from @rec where num>t.num)
/*
BeginTime EndTime num
------------------------------------------------------ ------------------------------------------------------ -----------
2003-04-02 12:03:04.000 2003-04-02 13:03:04.000 3
*/
ws_hgo 2009-04-07
  • 打赏
  • 举报
回复
你提供的好像有问题
人数这个字段了
ws_hgo 2009-04-07
  • 打赏
  • 举报
回复
等下
taoistong 2009-04-07
  • 打赏
  • 举报
回复


--最大
select top 1 max(1) from @tab group by EndTime-BeginTime --按照你的时间段来分组吧
order by max(1) desc
--最小
select top 1 min(1) from @tab group by EndTime-BeginTime --按照你的时间段来分组吧
order by min(1) desc

Teng_s2000 2009-04-07
  • 打赏
  • 举报
回复
哈哈,钻钻不合题意吧!!

感觉你应该自定义一个时间段,然后查询多少记录在在这个时间段吧
子陌红尘 2009-04-07
  • 打赏
  • 举报
回复
重新排个序,按照时间顺利列出连续的不同时段内使用人数:


declare @tab table(Id int,BeginTime datetime,EndTime datetime)
insert into @tab select 1,'2003-04-02 10:03:04','2003-4-02 13:03:04'
insert into @tab select 2,'2003-04-03 02:03:04','2003-4-03 03:03:04'
insert into @tab select 3,'2003-03-02 11:03:04','2003-4-02 13:03:04'
insert into @tab select 4,'2003-04-02 12:03:04','2003-4-02 13:03:04'
insert into @tab select 5,'2003-04-02 13:03:04','2003-4-02 15:03:04'
insert into @tab select 6,'2003-04-02 14:03:04','2009-4-02 17:03:04'


select
m.BeginTime,m.EndTime,count(n.id) as num
from
(select
a.BeginTime,min(b.EndTime) as EndTime
from
(select distinct BeginTime from @tab union all select distinct EndTime from @tab) a,
(select distinct EndTime from @tab union all select distinct BeginTime from @tab) b
where
a.BeginTime<b.EndTime
group by
a.BeginTime) m left join @tab n
on
(m.BeginTime between n.BeginTime and n.EndTime)
and
(m.EndTime between n.BeginTime and n.EndTime)
group by
m.BeginTime,m.EndTime
order by
m.BeginTime,m.EndTime

/*
BeginTime EndTime num
------------------------------------------------------ ------------------------------------------------------ -----------
2003-03-02 11:03:04.000 2003-04-02 10:03:04.000 1
2003-04-02 10:03:04.000 2003-04-02 12:03:04.000 2
2003-04-02 12:03:04.000 2003-04-02 13:03:04.000 3
2003-04-02 13:03:04.000 2003-04-02 14:03:04.000 1
2003-04-02 14:03:04.000 2003-04-02 15:03:04.000 2
2003-04-02 15:03:04.000 2003-04-03 02:03:04.000 1
2003-04-03 02:03:04.000 2003-04-03 03:03:04.000 2
2003-04-03 03:03:04.000 2009-04-02 17:03:04.000 1
*/
子陌红尘 2009-04-07
  • 打赏
  • 举报
回复
查出全部不同的时段使用人数:


declare @tab table(Id int,BeginTime datetime,EndTime datetime)
insert into @tab select 1,'2003-04-02 10:03:04','2003-4-02 13:03:04'
insert into @tab select 2,'2003-04-03 02:03:04','2003-4-03 03:03:04'
insert into @tab select 3,'2003-03-02 11:03:04','2003-4-02 13:03:04'
insert into @tab select 4,'2003-04-02 12:03:04','2003-4-02 13:03:04'
insert into @tab select 5,'2003-04-02 13:03:04','2003-4-02 15:03:04'
insert into @tab select 6,'2003-04-02 14:03:04','2009-4-02 17:03:04'


select
m.BeginTime,m.EndTime,count(n.id) as num
from
(select
a.BeginTime,min(b.EndTime) as EndTime
from
(select distinct BeginTime from @tab union all select distinct EndTime from @tab) a,
(select distinct EndTime from @tab union all select distinct BeginTime from @tab) b
where
a.BeginTime<b.EndTime
group by
a.BeginTime) m left join @tab n
on
(m.BeginTime between n.BeginTime and n.EndTime)
and
(m.EndTime between n.BeginTime and n.EndTime)
group by
m.BeginTime,m.EndTime
order by
num desc

/*
BeginTime EndTime num
------------------------------------------------------ ------------------------------------------------------ -----------
2003-04-02 12:03:04.000 2003-04-02 13:03:04.000 3
2003-04-02 10:03:04.000 2003-04-02 12:03:04.000 2
2003-04-02 14:03:04.000 2003-04-02 15:03:04.000 2
2003-04-03 02:03:04.000 2003-04-03 03:03:04.000 2
2003-04-03 03:03:04.000 2009-04-02 17:03:04.000 1
2003-04-02 15:03:04.000 2003-04-03 02:03:04.000 1
2003-03-02 11:03:04.000 2003-04-02 10:03:04.000 1
2003-04-02 13:03:04.000 2003-04-02 14:03:04.000 1
*/
  • 打赏
  • 举报
回复
可以,,但是觉得你的表结构不太完整(不是说数据的正确与否)到论坛里面搜索酒店房间利用率的帖子
http://topic.csdn.net/u/20090331/17/3910E2AA-4C44-47C8-8FDB-41D97B07D046.html
Zoezs 2009-04-07
  • 打赏
  • 举报
回复
你的时间段应该能知道吧?

22,222

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧