|
5#
楼主 |
发表于 2011-11-17 23:28:41
|
只看该作者
13.统计--交叉表+日期+优先.sql- SQL code --交叉表,根据优先级取数据,日期处理
- create table tb(qid int,rid nvarchar(4),tagname nvarchar(10),starttime smalldatetime,endtime smalldatetime,startweekday int,endweekday int,startdate smalldatetime,enddate smalldatetime,d int)
- insert tb select 1,'A1','未订','08:00','09:00',1 ,5 ,null ,null ,1
- union all select 1,'A1','未订','09:00','10:00',1 ,5 ,null ,null ,1
- union all select 1,'A1','未订','10:00','11:00',1 ,5 ,null ,null ,1
- union all select 1,'A1','装修','08:00','09:00',null,null,'2005-1-18','2005-1-19',2
- --union all select 1,'A1','装修','09:00','10:00',null,null,'2005-1-18','2005-1-19',2
- union all select 1,'A1','装修','10:00','11:00',null,null,'2005-1-18','2005-1-19',2
- union all select 1,'A2','未订','08:00','09:00',1 ,5 ,null ,null ,1
- union all select 1,'A2','未订','09:00','10:00',1 ,5 ,null ,null ,1
- union all select 1,'A2','未订','10:00','11:00',1 ,5 ,null ,null ,1
- --union all select 1,'A2','装修','08:00','09:00',null,null,'2005-1-18','2005-1-19',2
- union all select 1,'A2','装修','09:00','10:00',null,null,'2005-1-18','2005-1-19',2
- --union all select 1,'A2','装修','10:00','11:00',null,null,'2005-1-18','2005-1-19',2
- go
- /*--楼主这个问题要考虑几个方面
- 1. 取星期时,set datefirst 的影响
- 2. 优先级问题
- 3. qid,rid 应该是未知的(动态变化的)
- --*/
- --实现的存储过程如下
- create proc p_qry
- @date smalldatetime --要查询的日期
- as
- set nocount on
- declare @week int,@s nvarchar(4000)
- --格式化日期和得到星期
- select @date=convert(char(10),@date,120)
- ,@week=(@@datefirst+datepart(weekday,@date)-1)%7
- ,@s=''
- select id=identity(int),* into #t
- from(
- select top 100 percent
- qid,rid,tagname,
- starttime=convert(char(5),starttime,108),
- endtime=convert(char(5),endtime,108)
- from tb
- where (@week between startweekday and endweekday)
- or(@date between startdate and enddate)
- order by qid,rid,starttime,d desc)a
- select @s=@s+N',['+rtrim(rid)
- +N']=max(case when qid='+rtrim(qid)
- +N' and rid=N'''+rtrim(rid)
- +N''' then tagname else N'''' end)'
- from #t group by qid,rid
- exec('
- select starttime,endtime'+@s+'
- from #t a
- where not exists(
- select * from #t
- where qid=a.qid and rid=a.rid
- and starttime=a.starttime
- and endtime=a.endtime
- and id<a.id)
- group by starttime,endtime')
- go
- --调用
- exec p_qry '2005-1-17'
- exec p_qry '2005-1-18'
- go
- --删除测试
- drop table tb
- drop proc p_qry
- /*--测试结果
- starttime endtime A1 A2
- --------- ------- ---------- ----------
- 08:00 09:00 未订 未订
- 09:00 10:00 未订 未订
- 10:00 11:00 未订 未订
- starttime endtime A1 A2
- --------- ------- ---------- ----------
- 08:00 09:00 装修 未订
- 09:00 10:00 未订 装修
- 10:00 11:00 装修 未订
- --*/
复制代码 14.工作日处理函数(标准节假日).sql- SQL code if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_WorkDay]') and xtype in (N'FN', N'IF', N'TF'))
- drop function [dbo].[f_WorkDay]
- GO
- --计算两个日期相差的工作天数
- CREATE FUNCTION f_WorkDay(
- @dt_begin datetime, --计算的开始日期
- @dt_end datetime --计算的结束日期
- )RETURNS int
- AS
- BEGIN
- DECLARE @workday int,@i int,@bz bit,@dt datetime
- IF @dt_begin>@dt_end
- SELECT @bz=1,@dt=@dt_begin,@dt_begin=@dt_end,@dt_end=@dt
- ELSE
- SET @bz=0
- SELECT @i=DATEDIFF(Day,@dt_begin,@dt_end)+1,
- @workday=@i/7*5,
- @dt_begin=DATEADD(Day,@i/7*7,@dt_begin)
- WHILE @dt_begin<=@dt_end
- BEGIN
- SELECT @workday=CASE
- WHEN (@@DATEFIRST+DATEPART(Weekday,@dt_begin)-1)%7 BETWEEN 1 AND 5
- THEN @workday+1 ELSE @workday END,
- @dt_begin=@dt_begin+1
- END
- RETURN(CASE WHEN @bz=1 THEN -@workday ELSE @workday END)
- END
- GO
- /*=================================================================*/
- if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_WorkDayADD]') and xtype in (N'FN', N'IF', N'TF'))
- drop function [dbo].[f_WorkDayADD]
- GO
- --在指定日期上,增加指定工作天数后的日期
- CREATE FUNCTION f_WorkDayADD(
- @date datetime, --基础日期
- @workday int --要增加的工作日数
- )RETURNS datetime
- AS
- BEGIN
- DECLARE @bz int
- --增加整周的天数
- SELECT @bz=CASE WHEN @workday<0 THEN -1 ELSE 1 END
- ,@date=DATEADD(Week,@workday/5,@date)
- ,@workday=@workday%5
- --增加不是整周的工作天数
- WHILE @workday<>0
- SELECT @date=DATEADD(Day,@bz,@date),
- @workday=CASE WHEN (@@DATEFIRST+DATEPART(Weekday,@date)-1)%7 BETWEEN 1 AND 5
- THEN @workday-@bz ELSE @workday END
- --避免处理后的日期停留在非工作日上
- WHILE (@@DATEFIRST+DATEPART(Weekday,@date)-1)%7 in(0,6)
- SET @date=DATEADD(Day,@bz,@date)
- RETURN(@date)
- END
复制代码 15.工作日处理函数(自定义节假日).sql- SQL code if exists (select * from dbo.sysobjects where id = object_id(N'[tb_Holiday]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
- drop table [tb_Holiday]
- GO
- --定义节假日表
- CREATE TABLE tb_Holiday(
- HDate smalldatetime primary key clustered, --节假日期
- Name nvarchar(50) not null) --假日名称
- GO
- if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_WorkDay]') and xtype in (N'FN', N'IF', N'TF'))
- drop function [dbo].[f_WorkDay]
- GO
- --计算两个日期之间的工作天数
- CREATE FUNCTION f_WorkDay(
- @dt_begin datetime, --计算的开始日期
- @dt_end datetime --计算的结束日期
- )RETURNS int
- AS
- BEGIN
- IF @dt_begin>@dt_end
- RETURN(DATEDIFF(Day,@dt_begin,@dt_end)
- +1-(
- SELECT COUNT(*) FROM tb_Holiday
- WHERE HDate BETWEEN @dt_begin AND @dt_end))
- RETURN(-(DATEDIFF(Day,@dt_end,@dt_begin)
- +1-(
- SELECT COUNT(*) FROM tb_Holiday
- WHERE HDate BETWEEN @dt_end AND @dt_begin)))
- END
- GO
- if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_WorkDayADD]') and xtype in (N'FN', N'IF', N'TF'))
- drop function [dbo].[f_WorkDayADD]
- GO
- --在指定日期上增加工作天数
- CREATE FUNCTION f_WorkDayADD(
- @date datetime, --基础日期
- @workday int --要增加的工作日数
- )RETURNS datetime
- AS
- BEGIN
- IF @workday>0
- WHILE @workday>0
- SELECT @date=@date+@workday,@workday=count(*)
- FROM tb_Holiday
- WHERE HDate BETWEEN @date AND @date+@workday
- ELSE
- WHILE @workday<0
- SELECT @date=@date+@workday,@workday=-count(*)
- FROM tb_Holiday
- WHERE HDate BETWEEN @date AND @date+@workday
- RETURN(@date)
- END
复制代码 |
|