我有一个表,用于存储人们的轮班信息。其结构为:
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的一些建议。
也许有一些使用数据透视的方法,但这似乎是一种较慢的方法。
答案 0 :(得分:1)
说明
如果您不想使用动态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', '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,'HHmm','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
结果
答案 1 :(得分:1)
如何?
设置
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 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')
查询
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,
CASE WHEN DATEPART(dw,ShiftDate) = 2 THEN FORMAT(SHIFTSTart, 'HHmm') + '-' + FORMAT(ShiftEnd, 'HHmm') ELSE '' END AS Monday,
CASE WHEN DATEPART(dw,ShiftDate) = 3 THEN FORMAT(SHIFTSTart, 'HHmm') + '-' + FORMAT(ShiftEnd, 'HHmm') ELSE '' END AS Tuesday,
CASE WHEN DATEPART(dw,ShiftDate) = 4 THEN FORMAT(SHIFTSTart, 'HHmm') + '-' + FORMAT(ShiftEnd, 'HHmm') ELSE '' END AS Wednesday,
CASE WHEN DATEPART(dw,ShiftDate) = 5 THEN FORMAT(SHIFTSTart, 'HHmm') + '-' + FORMAT(ShiftEnd, 'HHmm') ELSE '' END AS Thursday,
CASE WHEN DATEPART(dw,ShiftDate) = 6 THEN FORMAT(SHIFTSTart, 'HHmm') + '-' + FORMAT(ShiftEnd, 'HHmm') ELSE '' END AS Friday,
CASE WHEN DATEPART(dw,ShiftDate) = 7 THEN FORMAT(SHIFTSTart, 'HHmm') + '-' + FORMAT(ShiftEnd, '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
答案 2 :(得分:1)
此方法将@userdate转换为wk_start日期,并使用它创建有条件聚合的数据透视表。
数据
CREATE TABLE test_TABLE
(
ShiftID INT,
PeopleID INT,
ShiftDate Date,
ShiftStart DATETIME,
ShiftEnd DATETIME
)
INSERT INTO test_TABLE
VALUES
(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');
查询
declare @userdate DATE='2020-08-25';
declare @wk_int int=datediff(wk, 0, @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,
isnull(max(case when datediff(d, @wk_start, t.ShiftDate)=1 then tm.hrs else null end), 'OFF') as Monday,
isnull(max(case when datediff(d, @wk_start, t.ShiftDate)=2 then tm.hrs else null end), 'OFF') as Tuesday,
isnull(max(case when datediff(d, @wk_start, t.ShiftDate)=3 then tm.hrs else null end), 'OFF') as Wednesday,
isnull(max(case when datediff(d, @wk_start, t.ShiftDate)=4 then tm.hrs else null end), 'OFF') as Thursday,
isnull(max(case when datediff(d, @wk_start, t.ShiftDate)=5 then tm.hrs else null end), 'OFF')as Friday,
isnull(max(case when datediff(d, @wk_start, 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)), ':', ''),
replace(convert(char(5),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