循环使用数据直到今天为止

时间:2018-04-24 01:43:48

标签: sql sql-server tsql

学生可以上课,并在Student_Hours表中记录他在课上花了多少小时。如果学生在100天内没有记录任何小时数,则被视为退学。需要查看“Student_Hours”表并查找他退出的所有时间,在下面的示例中,学生1在2017年1月1日的第一个联系时间和2017年5月1日的最后一个联系时间,并且在100以内没有联系时间这个日期和退出日期是8/9/2017(5/1/17 + 100)。

需要在第一个联系小时日期添加100天,查找此日期范围之间是否有任何小时,如果是,请将最后一个联系小时日期添加到此日期100天并查看此日期范围内的小时数,如果没有找到则添加100天到上次联系时间日期并将其作为退出日期。

学生

+----+------+
| Id | Name |
+----+------+
|  1 | a    |
|  2 | b    |
|  3 | c    |
|  4 | d    |
|  5 | e    |
+----+------+

班级

+----+------+
| Id | Name |
+----+------+
| 10 | c10  |
| 20 | c20  |
| 30 | c30  |
+----+------+

Student_Hours

+------------+----------+------------+-------+
| Student_Id | Class_Id | Hours_Date | Hours |
+------------+----------+------------+-------+
|          1 |       10 | 1/1/2017   |     2 |
|          1 |       10 | 3/1/2017   |     5 |
|          1 |       10 | 5/1/2017   |     6 |
|          1 |       20 | 12/1/2017  |     9 |
|          2 |       10 | 1/1/2017   |     1 |
|          2 |       10 | 1/31/2017  |     2 |
|          2 |       10 | 2/31/2017  |     2 |
|          2 |       10 | 7/5/2017   |     2 |
|          2 |       10 | 11/1/2017  |     4 |
|          2 |       10 | 3/1/2018   |     4 |
+------------+----------+------------+-------+

输出数据

+------------+-----------------------+------------+
| Student_Id | Last Contact Hrs Date | Exit Date  |
+------------+-----------------------+------------+
|          1 | 5/1/2017              | 8/9/2017   |
|          2 | 7/5/2017              | 10/31/2017 |
|          2 | 11/1/2017             | 2/9/2018   |
+------------+-----------------------+------------+

TIA

1 个答案:

答案 0 :(得分:0)

SQL Fiddle(MS SQL Server 2017架构)

中将其视为工作模型
CREATE TABLE Student  
    ([Id] int, [Name] varchar(100))
;

INSERT INTO Student  
    ([Id], [Name])
VALUES
    (1, 'a'),
    (2, 'b'),
    (3, 'c'),
    (4, 'd'),
    (5, 'e')
;

CREATE TABLE Class   
    ([Id] int, [Name] varchar(3))
;

INSERT INTO Class   
    ([Id], [Name])
VALUES
    (10, 'c10'),
    (20, 'c20'),
    (30, 'c30')
;

CREATE TABLE Student_Hours   
    ([Student_Id] int, [Class_Id] int, [Hours_Date] datetime, [Hours] int)
;

INSERT INTO Student_Hours   
    ([Student_Id], [Class_Id], [Hours_Date], [Hours])
VALUES
    (1, 10, '2017-01-01 11:00:00', 2),
    (1, 10, '2017-03-01 11:00:00', 5),
    (1, 10, '2017-05-01 10:00:00', 6),
    (1, 20, '2017-12-01 11:00:00', 9),
    (2, 10, '2017-01-01 11:00:00', 1),
    (2, 10, '2017-01-31 11:00:00', 2),
    (2, 10, '2017-03-03 11:00:00', 2),
    (2, 10, '2017-07-05 10:00:00', 2),
    (2, 10, '2017-11-01 11:00:00', 4),
    (2, 10, '2018-03-01 11:00:00', 4)
;

查询1

select 
       s.name AS student_name
     , sh.class_name
     , sh.mindate
     , max(case when sh.in_100days = 1 then hours_date end) latest_in100days
from student s
left join (
    select
           student_id
         , c.name as class_name
         , min(hours_date) over(partition by student_id, class_id) AS mindate
         , hours_date
         , case when hours_date <= dateadd(dd,100,min(hours_date) over(partition by student_id, class_id)) then 1 else 0 end AS in_100days
    from student_hours sh
    inner join class c on sh.class_id = c.id
    ) sh on s.id = sh.student_id
group by
       s.name
     , sh.class_name
     , sh.mindate
order by
       s.name
     , sh.class_name

<强> Results

| student_name | class_name |              mindate |     latest_in100days |
|--------------|------------|----------------------|----------------------|
|            a |        c10 | 2017-01-01T11:00:00Z | 2017-03-01T11:00:00Z |
|            a |        c20 | 2017-12-01T11:00:00Z | 2017-12-01T11:00:00Z |
|            b |        c10 | 2017-01-01T11:00:00Z | 2017-03-03T11:00:00Z |
|            c |     (null) |               (null) |               (null) |
|            d |     (null) |               (null) |               (null) |
|            e |     (null) |               (null) |               (null) |