获取有关特定日期免费人员的时间信息

时间:2016-10-24 10:29:23

标签: sql sql-server sql-server-2008 tsql

我有以下数据:

CREATE TABLE Table1 
(
     ID varchar(10),
     StudentName varchar(30), 
     Course varchar(15),
     SECTION varchar(2),
     DAY varchar(10),
     START_TIME time, 
     END_TIME time, 
     actual_starttime time, 
     actual_endtime time
);

INSERT INTO Table1 
VALUES (111, 'Mary', 'Science', 'A', 'Mon', '13:30:00.0000000', '16:20:00.0000000', '09:00:00.0000000', '21:20:00.0000000')
INSERT INTO Table1 
VALUES (111, 'Mary', 'Maths', 'A', 'Tue', '12:30:00.0000000', '13:20:00.0000000', '09:00:00.0000000', '21:20:00.0000000')
INSERT INTO Table1 
VALUES (111, 'Mary', 'Physics', 'C', 'Tue', '10:30:00.0000000', '11:10:00.0000000', '09:00:00.0000000', '21:20:00.0000000')
INSERT INTO Table1 
VALUES (112, 'Robert', 'Maths', 'A', 'Mon', '13:30:00.0000000', '16:20:00.0000000', '09:00:00.0000000', '21:20:00.0000000')

场景如下:学生可以在周一至周五的早上9点到晚上9点30分。我的要求是我必须确定一个时间段,同一部分的所有学生都是免费的,以便教师可以重新安排课程。

例子:玛丽和罗伯特在星期一下午9点到1点30分都是免费的。我想为此写一个查询。

请帮忙。

提前致谢!

4 个答案:

答案 0 :(得分:0)

您可以使用以下步骤创建存储过程。

步骤1:在另一个表格中预定义时间段(09:00-10:00,10:00-11:00等)

第2步:选择学生人数

第3步:

for all the slots
     Begin
           for all the students
          Begin
              if(students.actual_starttime =slots.actual_starttime and 
                 students.actual_endtime =slots.actual_endtime
              break;
             else count=count+1;
          End
     End

步骤4:如果以上计数与学生总数相匹配,则所有学生都可以免费使用插槽。其他插槽不适合所有学生。

希望这会有所帮助。如果你发现它有困难,请告诉我。

答案 1 :(得分:0)

你应该再增加三个表来使它更简单 即学生,科和插槽

我尝试再创建一个半小时的桌子

create table table2(timeslot time);

insert into table2 values ('9:00:00.0000000');
insert into table2 values ('9:30:00.0000000');
insert into table2 values ('10:00:00.0000000');
insert into table2 values ('10:30:00.0000000');
insert into table2 values ('11:00:00.0000000');
insert into table2 values ('11:30:00.0000000');
insert into table2 values ('12:00:00.0000000');
insert into table2 values ('12:30:00.0000000');
insert into table2 values ('13:00:00.0000000');
insert into table2 values ('13:30:00.0000000');
insert into table2 values ('14:00:00.0000000');
insert into table2 values ('14:30:00.0000000');
insert into table2 values ('15:00:00.0000000');
insert into table2 values ('15:30:00.0000000');
insert into table2 values ('16:00:00.0000000');
insert into table2 values ('16:30:00.0000000');
insert into table2 values ('17:00:00.0000000');
insert into table2 values ('17:30:00.0000000');
insert into table2 values ('18:00:00.0000000');
insert into table2 values ('18:30:00.0000000');
insert into table2 values ('19:00:00.0000000');
insert into table2 values ('19:30:00.0000000');
insert into table2 values ('20:00:00.0000000');
insert into table2 values ('20:30:00.0000000');
insert into table2 values ('21:00:00.0000000');
insert into table2 values ('21:30:00.0000000');

以下SQL将为您提供免费插槽和学生姓名:

<强>查询:

select t1.StudentName,t2.timeslot
from Table2 t2,
Table1 t1
where t2.timeslot<t1.start_time
and t2.timeslot<t1.end_time
and t1.section='A'
group by t1.StudentName,t2.timeslot
order by t2.timeslot

<强>输出:

    StudentName timeslot
1   Mary    09:00:00
2   Robert  09:00:00
3   Mary    09:30:00
4   Robert  09:30:00
5   Mary    10:00:00
6   Robert  10:00:00
7   Mary    10:30:00
8   Robert  10:30:00
9   Mary    11:00:00
10  Robert  11:00:00
11  Mary    11:30:00
12  Robert  11:30:00
13  Mary    12:00:00
14  Robert  12:00:00
15  Mary    12:30:00
16  Robert  12:30:00
17  Mary    13:00:00
18  Robert  13:00:00

这只是完成的一半任务,我只是告诉你实现它的方法。为了达到这个目的,在学生和科目表中再引入两个联接。

答案 2 :(得分:0)

将当天(09:00至21:30间隔)分成几分钟,找到关于该组学生的免费分钟数以及感兴趣的天数和分组间隔时间。

CREATE TABLE Table1 (ID varchar(10),StudentName varchar(30), Course varchar(15) ,SECTION varchar(2),DAY varchar(10),
START_TIME time , END_TIME time, actual_starttime time, actual_endtime time);

INSERT INTO Table1 VALUES (111, 'Mary','Science','A','Mon','13:30:00.0000000','16:20:00.0000000','09:00:00.0000000','21:20:00.0000000')
INSERT INTO Table1 VALUES (111, 'Mary','Maths','A','Tue','12:30:00.0000000','13:20:00.0000000','09:00:00.0000000','21:20:00.0000000')
INSERT INTO Table1 VALUES (111, 'Mary','Physics','C','Tue','10:30:00.0000000','11:10:00.0000000','09:00:00.0000000','21:20:00.0000000')
INSERT INTO Table1 VALUES (112, 'Robert','Maths','A','Mon','13:30:00.0000000','16:20:00.0000000','09:00:00.0000000','21:20:00.0000000')
;

-- parameters

declare @tds time = '09:00';
declare @tde time = '21:30';

declare @section varchar(2) = 'A';

create table #daysofinterest (DAY varchar(10) primary key);
insert  #daysofinterest (DAY) values ('Mon'),('Tue'),('Fri');

create table #groupmembers(ID int primary key);
insert #groupmembers(ID) values (111),(112);

-- query
select DAY, startt = dateadd(minute, min(n), @tds), endt = dateadd (minute, max(n), @tds)
from (
    select DAY, n, grp = n - row_number() over(partition by DAY order by n) 
    from (
      -- all minutes of the day, @tds till @tde
      select top (datediff(minute, @tds, @tde)) n = row_number() over(order by (select null))
      from sys.all_objects 
    ) tally
    cross join #daysofinterest dd
    join #groupmembers gm on
       not exists (select 1 from table1 t 
                   where t.ID = gm.ID and t.DAY = dd.DAY and SECTION = @section and
                   dateadd (minute, n, @tds) between t.START_TIME and t.END_TIME )

    group by DAY, n
    --this minute is free for every group member
    having count(*) = (select count(*) from #groupmembers)
) g
group by DAY, grp
order by DAY, min(n)

答案 3 :(得分:0)

要返回可用时间段的完整列表,您需要为一周中的每一天构建一组所有时间段,然后查找这些时段中是否有任何一个在其中教授学生。

这可以通过递归CTE轻松实现,以构建完整的时间段集,您可以从中加入学生数据。以下查询的输出是每个空缺会议的日期和时间:

-- Build the dummy data sets:

declare @Data table
(
     ID varchar(10),
     StudentName varchar(30), 
     Course varchar(15),
     SECTION varchar(2),
     DAY varchar(10),
     START_TIME time, 
     END_TIME time, 
     actual_starttime time, 
     actual_endtime time
);

insert into @Data values
 (111, 'Mary', 'Science', 'A', 'Mon', '13:30:00.0000000', '16:20:00.0000000', '09:00:00.0000000', '21:20:00.0000000')
,(111, 'Mary', 'Maths', 'A', 'Tue', '12:30:00.0000000', '13:20:00.0000000', '09:00:00.0000000', '21:20:00.0000000')
,(111, 'Mary', 'Physics', 'C', 'Tue', '10:30:00.0000000', '11:10:00.0000000', '09:00:00.0000000', '21:20:00.0000000')
,(112, 'Robert', 'Maths', 'A', 'Mon', '13:30:00.0000000', '16:20:00.0000000', '09:00:00.0000000', '21:20:00.0000000');



-- Query the data:

with TimeSlots as   -- Recursive CTE builds a table of all timeslots in TIME data type.
(
    select cast('09:00:00' as time) as TimeSlotStart
            ,cast('09:30:00' as time) as TimeSlotEnd
    union all
    select dateadd(minute,30,TimeSlotStart)
            ,dateadd(minute,30,TimeSlotEnd)
    from TimeSlots
    where TimeSlotStart < cast('21:00:00' as time)
)
, TeachingDays as   -- Used to return all the time slots above for each day of the week in CROSS JOIN below.
(
    select 1 as DaySort
        ,'Mon' as TeachingDay
    union all
    select 2 as DaySort
        ,'Tue'
    union all
    select 3 as DaySort
        ,'Wed'
    union all
    select 4 as DaySort
        ,'Thu'
    union all
    select 5 as DaySort
        ,'Fri'
)
select td.TeachingDay
        ,t.TimeSlotStart
        ,t.TimeSlotEnd
from TimeSlots t                    -- Select all timeslots.
    cross join TeachingDays td      -- For each day.
    left join @Data d               -- And find all students that are being taught on that day at the specified time.
        on(td.TeachingDay = d.DAY
            and t.TimeSlotStart <= d.END_TIME
            and t.TimeSlotEnd > d.START_TIME
            )
where d.ID is null                  -- Then only return data where there are no students being taught at this timeslot.
order by td.DaySort
        ,t.TimeSlotStart;