问题描述
SHIFT_TABLE
-----------
ShiftID PeopleID ShiftDate ShiftStart ShiftEnd
1 41 2020-08-24 2020-08-24 06:00 2020-08-24 14:00
2 41 2020-08-26 2020-08-26 06:00 2020-08-26 14:00
3 41 2020-08-27 2020-08-27 19:00 2020-08-28 03:00
4 41 2020-08-29 2020-08-29 10:00 2020-08-29 16:00
5 58 2020-08-24 2020-08-24 14:00 2020-08-24 21:30
6 58 2020-08-25 2020-08-25 14:00 2020-08-25 23:00
7 58 2020-08-30 2020-08-30 08:00 2020-08-30 18:00
Columns Data types
------- ----------
ShiftDate date
ShiftStart datetime
ShiftEnd datetime
用户将只发送一个日期(无时间),新的存储过程将返回该周(从星期日到星期六)所有人员的轮班信息。因此,如果use从一个星期中选择任何日期,例如星期一或星期三,结果将完全相同。
例如,如果用户将2020-08-25
发送给SP,则将返回除ShiftID为7的行以外的所有行。
发送2020-08-25
时,结果应如下所示:
Person 2020-08-23 2020-08-24 2020-08-25 2020-08-26 2020-08-27 2020-08-28 2020-08-29
41 OFF 06:00-14:00 OFF 06:00-14:00 19:00-03:00 OFF 10:00-16:00
58 OFF 14:00-21:30 14:00-21:30 OFF OFF OFF OFF
不用日期作为列名,我可以使用日期名,因为这种方法可以避免使用动态sql:
Person Sunday Monday Tuesday Wednesday Thursday Friday Saturday
41 OFF 06:00-14:00 OFF 06:00-14:00 19:00-03:00 OFF 10:00-16:00
58 OFF 14:00-21:30 14:00-21:30 OFF OFF OFF OFF
我想避免使用动态sql或XML solutions。我可以获得工作日编号(1代表星期日,2代表星期一,依此类推)。我不确定这是否会有所帮助。有没有一种方法可以将ShiftStart
和ShiftEnd
列与PoepleID
换位。我已经可以用ShiftDate
过滤结果集。列名将每周更改一次。我想不惜一切代价避免使用动态sql的一些建议。
解决方法
说明
如果您不想使用动态sql,并且可以使用“星期一,星期二...星期日” (或每天等值的数字1 =星期一,2 =星期二)就可以了。 ..)作为列标题,而不是像“ 2020.08.23 2020.08.24 2020.08.25 2020.08.26 2020.08.27 2020.08.28 2020.08.29” 之类的实际日期值,则可以实现您的要求:>
查询
declare @WorkDate date = '2020.08.25',@StartFilter date,@EndFilter date
declare @shift_table table ( ShiftID int identity(1,1),PeopleID int,ShiftDate varchar(max),ShiftStart datetime,ShiftEnd datetime )
insert into @shift_table (PeopleID,ShiftDate,ShiftStart,ShiftEnd )
select 41,'2020.08.24','2020-08-24 06:00','2020-08-24 14:00'
union select 41,'2020.08.26','2020-08-26 06:00','2020-08-26 14:00'
union select 41,'2020.08.27','2020-08-27 19:00','2020-08-28 03:00'
union select 41,'2020.08.29','2020-08-29 10:00','2020-08-29 16:00'
union select 58,'2020-08-24 14:00','2020-08-24 21:30'
union select 58,'2020.08.25','2020-08-25 14:00','2020-08-25 23:00'
union select 58,'2020.08.30','2020-08-30 08:00','2020-08-30 18:00'
-- get the week start and end date filters based on the @WorkDate passed in
SELECT @StartFilter = DATEADD(dd,-(DATEPART(dw,@WorkDate)-1),@WorkDate) /* week start */,@EndFilter = DATEADD(dd,7-(DATEPART(dw,@WorkDate)),@WorkDate) /* week end */
select
Person,min(Monday) as [Monday],min(Tuesday) as [Tuesday],min(Wednesday) as [Wednesday],min(Thursday) as [Thursday],min(Friday) as [Friday],min(Saturday) as [Saturday],min(Sunday) as [Sunday]
from (
select
PeopleID as Person,isnull([Monday],'OFF') as [Monday],isnull([Tuesday],'OFF') as [Tuesday],isnull([Wednesday],'OFF') as [Wednesday],isnull([Thursday],'OFF') as [Thursday],isnull([Friday],'OFF') as [Friday],isnull([Saturday],'OFF') as [Saturday],isnull([Sunday],'OFF') as [Sunday]
from (
select
*,DATENAME(dw,cast(ShiftDate as date)) [Day],format(ShiftStart,'HHmm','en-us') + '-' + format(ShiftEnd,'en-us') ShiftTime
from @shift_table
where cast(ShiftDate as date) between @StartFilter and @EndFilter
) src
pivot
(
max(ShiftTime)
for [Day] in ([Monday],[Tuesday],[Wednesday],[Thursday],[Friday],[Saturday],[Sunday])
) piv
) P
group by P.Person
结果
,如何?
设置
CREATE TABLE SHIFT_TABLE
(
ShiftID INT,PeopleID INT,ShiftDate Date,ShiftStart DATETIME,ShiftEnd DATETIME
)
INSERT INTO SHIFT_Table
VALUES
(1,41,'2020-08-24','2020-08-24 14:00'),(2,'2020-08-26','2020-08-26 14:00'),(3,'2020-08-27','2020-08-28 03:00'),(4,'2020-08-29','2020-08-29 16:00'),(5,58,'2020-08-24 21:30'),(6,'2020-08-25','2020-08-25 23:00'),(7,'2020-08-30','2020-08-30 18:00')
查询
DECLARE @userdate DATE = '2020-08-25'
SELECT PeopleID,CASE WHEN MAX(Sunday) = '' THEN 'OFF' ELSE Max(Sunday) END AS Sunday,CASE WHEN MAX(Monday) = '' THEN 'OFF' ELSE Max(Monday) END AS Monday,CASE WHEN MAX(Tuesday) = '' THEN 'OFF' ELSE Max(Tuesday) END AS Tuesday,CASE WHEN MAX(Wednesday) = '' THEN 'OFF' ELSE Max(Wednesday) END AS Wednesday,CASE WHEN MAX(Thursday) = '' THEN 'OFF' ELSE Max(Thursday) END AS Thursday,CASE WHEN MAX(Friday) = '' THEN 'OFF' ELSE Max(Friday) END AS Friday,CASE WHEN MAX(Saturday) = '' THEN 'OFF' ELSE Max(Saturday) END AS Saturday
FROM
(
SELECT
PeopleId,CASE WHEN DATEPART(dw,ShiftDate) = 1 THEN FORMAT(SHIFTSTart,'HHmm') + '-' + FORMAT(ShiftEnd,'HHmm') ELSE '' END AS Sunday,ShiftDate) = 2 THEN FORMAT(SHIFTSTart,'HHmm') ELSE '' END AS Monday,ShiftDate) = 3 THEN FORMAT(SHIFTSTart,'HHmm') ELSE '' END AS Tuesday,ShiftDate) = 4 THEN FORMAT(SHIFTSTart,'HHmm') ELSE '' END AS Wednesday,ShiftDate) = 5 THEN FORMAT(SHIFTSTart,'HHmm') ELSE '' END AS Thursday,ShiftDate) = 6 THEN FORMAT(SHIFTSTart,'HHmm') ELSE '' END AS Friday,ShiftDate) = 7 THEN FORMAT(SHIFTSTart,'HHmm') ELSE '' END AS Saturday
FROM SHIFT_TABLE
WHERE DATEPART(Week,ShiftDate) = DATEPART(Week,@UserDate)
) s
GROUP BY PeopleID
结果
PeopleID Sunday Monday Tuesday Wednesday Thursday Friday Saturday
41 OFF 0600-1400 OFF 0600-1400 1900-0300 OFF 1000-1600
58 OFF 1400-2130 1400-2300 OFF OFF OFF OFF
,
此方法将@userdate转换为wk_start日期,并使用它创建有条件聚合的数据透视表。
数据
CREATE TABLE test_TABLE
(
ShiftID INT,ShiftEnd DATETIME
)
INSERT INTO test_TABLE
VALUES
(1,'2020-08-30 18:00');
查询
declare @userdate DATE='2020-08-25';
declare @wk_int int=datediff(wk,@userdate);
declare @wk_start date=dateadd(d,-1,dateadd(wk,@wk_int,0));
SELECT PeopleID,isnull(max(case when datediff(d,@wk_start,t.ShiftDate)=0 then tm.hrs else null end),'OFF') as Sunday,t.ShiftDate)=1 then tm.hrs else null end),'OFF') as Monday,t.ShiftDate)=2 then tm.hrs else null end),'OFF') as Tuesday,t.ShiftDate)=3 then tm.hrs else null end),'OFF') as Wednesday,t.ShiftDate)=4 then tm.hrs else null end),'OFF') as Thursday,t.ShiftDate)=5 then tm.hrs else null end),'OFF')as Friday,t.ShiftDate)=6 then tm.hrs else null end),'OFF') as Saturday
FROM
test_TABLE t
cross apply
(select concat_ws('-',replace(convert(char(5),cast(ShiftStart as time)),':',''),cast(ShiftEnd as time)),'')) hrs) tm
where ShiftDate>=@wk_start
and ShiftDate<=dateadd(d,7,@wk_start)
group by
peopleid;
结果
PeopleID Sunday Monday Tuesday Wednesday Thursday Friday Saturday
41 OFF 0600-1400 OFF 0600-1400 1900-0300 OFF 1000-1600
58 OFF 1400-2130 1400-2300 OFF OFF OFF OFF