想不出来用SQL怎么写,关于在给定的时间段时查找对应关系并找出开始结束时间

dovefay 2013-06-06 07:30:21
数据库为 2008

表的结构如下


货柜 时间 司机
ccc 2013-06-01 13:30:31 ABC
yyy 2013-06-01 13:37:30 BMW
yyy 2013-06-01 13:40:31 BMW
ccc 2013-06-01 13:41:31 ABC
ccc 2013-06-01 13:45:20 ABC
yyy 2013-06-01 14:30:31 BMW

yyy 2013-06-02 11:40:31 BMW
ccc 2013-06-02 12:15:21 000
ccc 2013-06-02 13:10:30 000
ccc 2013-06-02 13:20:31 000
yyy 2013-06-02 13:40:31 BMW

ccc 2013-06-03 11:30:31 ABC
ccc 2013-06-03 12:40:31 ABC
ccc 2013-06-03 13:50:31 ABC
ccc 2013-06-03 14:55:31 ABC


需求是 要以货柜为单位,在一个给定时间段内所搭配的所有司机和开始和结束时间。

出来的结果应该像这样的(假设查从6月1号到6月20号的这个时间段)
货柜 起始时间 结束时间 司机
ccc 2013-06-01 13:30:31 2013-06-01 13:45:20 ABC
ccc 2013-06-02 12:15:21 2013-06-02 13:20:31 000
ccc 2013-06-03 11:30:31 2013-06-03 14:55:31 ABC
yyy 2013-06-01 13:37:30 2013-06-02 13:40:31 BMW

因为这个我原来是想顺序来读取,发现司机名字一换,就结束,再开始新的查询什么的。但是这个写程序的笨做法,用SQL我就不知道怎么写了。

求大家帮忙。
...全文
187 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
Flyinsky1 2013-06-07
  • 打赏
  • 举报
回复
这回用游标,应该很符合你的要求了:
DECLARE @container nvarchar(40)
DECLARE @starttime datetime
DECLARE @endtime datetime
DECLARE @curtime datetime
DECLARE @driver nvarchar(40)
DECLARE @curdriver nvarchar(40)
declare @curstate int
set @curstate=0
declare contcursor cursor
for select distinct(货柜)
FROM GROUBYTIME

open contcursor
fetch next from contcursor into @container

while @@FETCH_STATUS=0
begin
	declare timecursor cursor
	for select 时间,司机
	FROM GROUBYTIME
	where 货柜=@container
	open timecursor
	fetch next from timecursor into @curtime,@curdriver
	WHILE @@FETCH_STATUS = 0
	begin
		if @curstate=0
			begin --初始化
			set @driver=@curdriver
			set @starttime=@curtime
			set @endtime=@starttime
			set @curstate=1
			end
		if @driver<>@curdriver
			begin
			--换司机,获取结束时间,输出,更换开始时间
			select @container,@starttime,@endtime,@driver
			set @driver=@curdriver
			set @starttime=@curtime
			end
		else 
			begin
			--未换司机,更换结束时间
			set @endtime=@curtime
			end
		fetch next from timecursor into @curtime,@curdriver
	end
	select @container,@starttime,@endtime,@driver
	set @curstate=0--下一个货柜初始化
	close timecursor
	deallocate timecursor

	fetch next from contcursor into @container
end
close contcursor
deallocate contcursor
BzTech_123 2013-06-07
  • 打赏
  • 举报
回复

CREATE table GROUBYTIME(
Trailer NVARCHAR(40),
CheckedOn DATETIME,
Driver NVARCHAR(30))

INSERT INTO GROUBYTIME
SELECT'ccc','2013-06-01 13:30:31','ABC' UNION ALL
SELECT 'yyy','2013-06-01 13:37:30','BMW' UNION ALL
SELECT 'yyy','2013-06-01 13:40:31','BMW' UNION ALL
SELECT 'ccc','2013-06-01 13:41:31','ABC' UNION ALL
SELECT 'ccc','2013-06-01 13:45:20','ABC' UNION ALL
SELECT 'yyy','2013-06-01 14:30:31','BMW' UNION ALL
SELECT 'yyy','2013-06-02 11:40:31','BMW' UNION ALL
SELECT 'ccc','2013-06-02 12:15:21','000' UNION ALL
SELECT 'ccc','2013-06-02 13:10:30','000' UNION ALL
SELECT 'ccc','2013-06-02 13:20:31','000' UNION ALL
SELECT 'yyy','2013-06-02 13:40:31','BMW' UNION ALL
SELECT 'ccc','2013-06-03 11:30:31','ABC' UNION ALL
SELECT 'ccc','2013-06-03 12:40:31','ABC' UNION ALL
SELECT 'ccc','2013-06-03 13:50:31','ABC' UNION ALL
SELECT 'ccc','2013-06-03 14:55:31','ABC'


SELECT t1.Trailer, t1.CheckedOn AS StartTime, t2.CheckedOn AS EndTime
FROM
(SELECT Trailer,CheckedOn,Driver, ROW_NUMBER() OVER(PARTITION BY Trailer ORDER BY CheckedOn) AS Row FROM GROUBYTIME) t1
LEFT JOIN
(SELECT Trailer, CheckedOn, ROW_NUMBER() OVER(PARTITION BY Trailer ORDER BY CheckedOn) AS Row FROM GROUBYTIME) t2
ON t1.Trailer = t2.Trailer AND t1.Row = t2.Row -1
WHERE t1.Row % 2 = 1
ORDER BY t1.Trailer, t1.CheckedOn
dovefay 2013-06-07
  • 打赏
  • 举报
回复
引用 3 楼 u010933793 的回复:

DECLARE @Begin DATETIME, @END DATETIME 

SET @Begin = '06/01/2013'
SET @End = '06/02/2013'

SELECT 货柜,MIN(时间) as 开始时间,MAX(时间) as 结束时间,司机 
FROM GROUBYTIME 
WHERE CONVERT(VARCHAR(10), 时间, 102) BETWEEN CONVERT(VARCHAR(10),@Begin, 102) AND CONVERT(VARCHAR(10),@End,102) 
GROUP BY 货柜,司机

-- 如求每天一天之内的搭配

SELECT 货柜,MIN(时间) as 开始时间,MAX(时间) as 结束时间,司机 
FROM GROUBYTIME 
GROUP BY CONVERT(VARCHAR(10), 时间, 102), 货柜,司机

谢 谢 。 但是还有个问题,我写在回贴里了。不是要按天来统计,时间不定的,我当时就是为了按理解方便写的例子。
dovefay 2013-06-07
  • 打赏
  • 举报
回复
谢谢你的回答。 我试了下你的SQL,符合80%的需求了。但是还有一个问题。 我想出来的效果是在按时间来顺序显示搭配过的司机,例如上午9点开始,CCC货柜配ABC司机到11点,然后在11点的时候换人了,又换上DDD了,开到下午3点,在3点后,又换回ABC这个司机了。这种情况的话,用GROUP BY 只会出来司机的名字只会出来一次,而不会出现多次。 但是最理想的情况是做出这样的结果 ccc 2013-06-02 09:00:21.000 2013-06-02 11:00:31.000 ABC ccc 2013-06-02 11:01:31.000 2013-06-02 15:00:20.000 DDD ccc 2013-06-03 15:00:31.000 2013-06-03 17:30:31.000 ABC yyy 2013-06-01 13:37:30.000 2013-06-02 13:40:31.000 BMW
引用 2 楼 Flyinsky1 的回复:
若按每日计算,以下貌似能符合你的要求,2000,2008均可
/*create table GROUBYTIME(
货柜 NVARCHAR(40),
时间 DATETIME,
司机 NVARCHAR(30))
INSERT INTO GROUBYTIME
SELECT'ccc','2013-06-01 13:30:31','ABC' UNION ALL 
SELECT 'yyy','2013-06-01 13:37:30','BMW' UNION ALL 
SELECT 'yyy','2013-06-01 13:40:31','BMW' UNION ALL 
SELECT 'ccc','2013-06-01 13:41:31','ABC' UNION ALL 
SELECT 'ccc','2013-06-01 13:45:20','ABC' UNION ALL 
SELECT 'yyy','2013-06-01 14:30:31','BMW' UNION ALL 
SELECT 'yyy','2013-06-02 11:40:31','BMW' UNION ALL 
SELECT 'ccc','2013-06-02 12:15:21','000' UNION ALL 
SELECT 'ccc','2013-06-02 13:10:30','000' UNION ALL 
SELECT 'ccc','2013-06-02 13:20:31','000' UNION ALL 
SELECT 'yyy','2013-06-02 13:40:31','BMW' UNION ALL 
SELECT 'ccc','2013-06-03 11:30:31','ABC' UNION ALL 
SELECT 'ccc','2013-06-03 12:40:31','ABC' UNION ALL 
SELECT 'ccc','2013-06-03 13:50:31','ABC' UNION ALL 
SELECT 'ccc','2013-06-03 14:55:31','ABC'*/
SELECT 货柜,时间,司机 FROM GROUBYTIME
SELECT 货柜,MIN(时间) as 开始时间,MAX(时间) as 结束时间,司机 FROM GROUBYTIME GROUP BY 货柜,司机,DAY(时间)
ccc	2013-06-02 12:15:21.000	2013-06-02 13:20:31.000	000
ccc	2013-06-01 13:30:31.000	2013-06-01 13:45:20.000	ABC
ccc	2013-06-03 11:30:31.000	2013-06-03 14:55:31.000	ABC
yyy	2013-06-01 13:37:30.000	2013-06-01 14:30:31.000	BMW
yyy	2013-06-02 11:40:31.000	2013-06-02 13:40:31.000	BMW
2013-06-01 14:30:31.000 -2013-06-02 11:40:31.000 BMW还开?
BzTech_123 2013-06-06
  • 打赏
  • 举报
回复

DECLARE @Begin DATETIME, @END DATETIME 

SET @Begin = '06/01/2013'
SET @End = '06/02/2013'

SELECT 货柜,MIN(时间) as 开始时间,MAX(时间) as 结束时间,司机 
FROM GROUBYTIME 
WHERE CONVERT(VARCHAR(10), 时间, 102) BETWEEN CONVERT(VARCHAR(10),@Begin, 102) AND CONVERT(VARCHAR(10),@End,102) 
GROUP BY 货柜,司机

-- 如求每天一天之内的搭配

SELECT 货柜,MIN(时间) as 开始时间,MAX(时间) as 结束时间,司机 
FROM GROUBYTIME 
GROUP BY CONVERT(VARCHAR(10), 时间, 102), 货柜,司机

Flyinsky1 2013-06-06
  • 打赏
  • 举报
回复
若按每日计算,以下貌似能符合你的要求,2000,2008均可
/*create table GROUBYTIME(
货柜 NVARCHAR(40),
时间 DATETIME,
司机 NVARCHAR(30))
INSERT INTO GROUBYTIME
SELECT'ccc','2013-06-01 13:30:31','ABC' UNION ALL 
SELECT 'yyy','2013-06-01 13:37:30','BMW' UNION ALL 
SELECT 'yyy','2013-06-01 13:40:31','BMW' UNION ALL 
SELECT 'ccc','2013-06-01 13:41:31','ABC' UNION ALL 
SELECT 'ccc','2013-06-01 13:45:20','ABC' UNION ALL 
SELECT 'yyy','2013-06-01 14:30:31','BMW' UNION ALL 
SELECT 'yyy','2013-06-02 11:40:31','BMW' UNION ALL 
SELECT 'ccc','2013-06-02 12:15:21','000' UNION ALL 
SELECT 'ccc','2013-06-02 13:10:30','000' UNION ALL 
SELECT 'ccc','2013-06-02 13:20:31','000' UNION ALL 
SELECT 'yyy','2013-06-02 13:40:31','BMW' UNION ALL 
SELECT 'ccc','2013-06-03 11:30:31','ABC' UNION ALL 
SELECT 'ccc','2013-06-03 12:40:31','ABC' UNION ALL 
SELECT 'ccc','2013-06-03 13:50:31','ABC' UNION ALL 
SELECT 'ccc','2013-06-03 14:55:31','ABC'*/
SELECT 货柜,时间,司机 FROM GROUBYTIME
SELECT 货柜,MIN(时间) as 开始时间,MAX(时间) as 结束时间,司机 FROM GROUBYTIME GROUP BY 货柜,司机,DAY(时间)
ccc	2013-06-02 12:15:21.000	2013-06-02 13:20:31.000	000
ccc	2013-06-01 13:30:31.000	2013-06-01 13:45:20.000	ABC
ccc	2013-06-03 11:30:31.000	2013-06-03 14:55:31.000	ABC
yyy	2013-06-01 13:37:30.000	2013-06-01 14:30:31.000	BMW
yyy	2013-06-02 11:40:31.000	2013-06-02 13:40:31.000	BMW
2013-06-01 14:30:31.000 -2013-06-02 11:40:31.000 BMW还开?
yo_yo1120 2013-06-06
  • 打赏
  • 举报
回复
看你给的例子,不明白怎么区分起始时间/结束时间。

22,209

社区成员

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

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