Search code examples
sql-serverjoinrow-number

Joining DB tables: repeat values in one table for each group in second table


Students are absent from classes, I have to calculate consecutive absences. 'Date' table has all dates in school year, and indicates if school is in session. Not in session for weekends or holidays. 'Absence' table lists students and the dates they were absent from specific class. I need to list all dates for each 'CLASS' group to see if a class is missed for consecutive days. I have tried CROSS JOIN, couldn't get it to work. Maybe ROW_NUMBER can be used. Any type of solution is welcome!

enter image description here

Date table with dates school is in session. Absence tables with days a student is absent and which class. Last picture is table I want to create. I would like to repeat the dates in the range for each Student/Class group

enter image description here


Solution

  • Try something like the following. You can run this example in SSMS.

    DECLARE @Absent table ( stu_id varchar(10), class varchar(10), absent_date date );
    INSERT INTO @Absent VALUES
        ( 'Billie', 'English', '11/03/2020' ),
        ( 'Billie', 'Math', '11/10/2020' ),
        ( 'Billie', 'Math', '11/12/2020' ),
        ( 'Billie', 'Science', '11/19/2020' ),
        ( 'Billie', 'Math', '11/19/2020' );
    
    DECLARE @InSession table ( CalDate date, InSession bit );
    INSERT INTO @InSession VALUES
        ( '11/02/2020', 1 ),( '11/03/2020', 1 ),( '11/04/2020', 1 ),( '11/05/2020', 1 ),( '11/06/2020', 1 ),( '11/07/2020', 0 ),( '11/08/2020', 0 ),
        ( '11/09/2020', 1 ),( '11/10/2020', 1 ),( '11/11/2020', 0 ),( '11/12/2020', 1 ),( '11/13/2020', 1 ),( '11/14/2020', 0 ),
        ( '11/15/2020', 0 ),( '11/16/2020', 1 ),( '11/17/2020', 1 ),( '11/18/2020', 1 ),( '11/19/2020', 1 ),( '11/20/2020', 0 );
    
    SELECT DISTINCT
        FORMAT ( s.CalDate, 'MM/dd/yyyy' ) AS CalDate,
        s.InSession,
        a.stu_id,
        CASE 
            WHEN a.absent_date = s.CalDate THEN a.class
            ELSE ''
        END AS class,
        CASE
            WHEN a.absent_date = s.CalDate THEN FORMAT ( a.absent_date, 'MM/dd/yyyy' )
            ELSE ''
        END AS absent_date
    FROM @InSession AS s
    CROSS APPLY @Absent AS a
    ORDER BY
        s.CalDate;
    

    Returns

    +------------+-----------+--------+---------+-------------+
    |  CalDate   | InSession | stu_id |  class  | absent_date |
    +------------+-----------+--------+---------+-------------+
    | 2020-11-02 |         1 | Billie |         |             |
    | 2020-11-03 |         1 | Billie |         |             |
    | 2020-11-03 |         1 | Billie | English | 11/03/2020  |
    | 2020-11-04 |         1 | Billie |         |             |
    | 2020-11-05 |         1 | Billie |         |             |
    | 2020-11-06 |         1 | Billie |         |             |
    | 2020-11-07 |         0 | Billie |         |             |
    | 2020-11-08 |         0 | Billie |         |             |
    | 2020-11-09 |         1 | Billie |         |             |
    | 2020-11-10 |         1 | Billie |         |             |
    | 2020-11-10 |         1 | Billie | Math    | 11/10/2020  |
    | 2020-11-11 |         0 | Billie |         |             |
    | 2020-11-12 |         1 | Billie |         |             |
    | 2020-11-12 |         1 | Billie | Math    | 11/12/2020  |
    | 2020-11-13 |         1 | Billie |         |             |
    | 2020-11-14 |         0 | Billie |         |             |
    | 2020-11-15 |         0 | Billie |         |             |
    | 2020-11-16 |         1 | Billie |         |             |
    | 2020-11-17 |         1 | Billie |         |             |
    | 2020-11-18 |         1 | Billie |         |             |
    | 2020-11-19 |         1 | Billie |         |             |
    | 2020-11-19 |         1 | Billie | Math    | 11/19/2020  |
    | 2020-11-19 |         1 | Billie | Science | 11/19/2020  |
    | 2020-11-20 |         0 | Billie |         |             |
    +------------+-----------+--------+---------+-------------+
    

    Note that on 11/19/2020 Billie is marked absent from two classes, creating multiple results for the day.

    You will also receive a blank row in addition to an "absent" row on days an absence has been reported. I'm looking to see if I can resolve this part.

    UPDATE

    Removed the "empty" rows on absent days.

    SELECT DISTINCT
            s.CalDate,
            s.InSession,
            a.stu_id,
            ISNULL ( x.class, '' ) AS class,
            ISNULL ( x.absent_date, '' ) AS absent_date
        FROM @InSession AS s
        CROSS APPLY @Absent AS a
        OUTER APPLY (
            
            SELECT
                ab.class, CONVERT ( varchar(10), ab.absent_date, 101 ) AS absent_date
            FROM @Absent AS ab
            WHERE
                ab.stu_id = a.stu_id
                AND ab.absent_date = s.CalDate
    
        ) AS x
        ORDER BY
            s.CalDate, stu_id, absent_date;
    

    Returns

    +------------+-----------+--------+---------+-------------+
    |  CalDate   | InSession | stu_id |  class  | absent_date |
    +------------+-----------+--------+---------+-------------+
    | 2020-11-02 |         1 | Billie |         |             |
    | 2020-11-03 |         1 | Billie | English | 11/03/2020  |
    | 2020-11-04 |         1 | Billie |         |             |
    | 2020-11-05 |         1 | Billie |         |             |
    | 2020-11-06 |         1 | Billie |         |             |
    | 2020-11-07 |         0 | Billie |         |             |
    | 2020-11-08 |         0 | Billie |         |             |
    | 2020-11-09 |         1 | Billie |         |             |
    | 2020-11-10 |         1 | Billie | Math    | 11/10/2020  |
    | 2020-11-11 |         0 | Billie |         |             |
    | 2020-11-12 |         1 | Billie | Math    | 11/12/2020  |
    | 2020-11-13 |         1 | Billie |         |             |
    | 2020-11-14 |         0 | Billie |         |             |
    | 2020-11-15 |         0 | Billie |         |             |
    | 2020-11-16 |         1 | Billie |         |             |
    | 2020-11-17 |         1 | Billie |         |             |
    | 2020-11-18 |         1 | Billie |         |             |
    | 2020-11-19 |         1 | Billie | Math    | 11/19/2020  |
    | 2020-11-19 |         1 | Billie | Science | 11/19/2020  |
    | 2020-11-20 |         0 | Billie |         |             |
    +------------+-----------+--------+---------+-------------+
    

    UPDATE

    So I want the date range, Nov 2 - 20, repeated for every CLASS and every STUDENT included in the raw data.

    Try this:

    SELECT
        CalDate,
        InSession,
        stu_id,
        class,
        MAX ( absent_date ) AS absent_date
    FROM (
    
        SELECT DISTINCT
            CalDate,
            InSession,
            stu_id, 
            x.class,
            CASE
                WHEN x.absent_date = CalDate THEN CONVERT ( varchar(10), x.absent_date, 101 )
                ELSE ''
            END AS absent_date
        FROM @InSession AS i
        CROSS APPLY @Absent AS a
        OUTER APPLY (
            
                SELECT
                    ab.class, CONVERT ( varchar(10), ab.absent_date, 101 ) AS absent_date
                FROM @Absent AS ab
                WHERE
                    ab.stu_id = a.stu_id
                    AND ab.absent_date = a.absent_date
    
            ) AS x
        WHERE
            i.CalDate BETWEEN '11/02/2020' AND '11/30/2020'
    
    ) AS StudentAbsent
    GROUP BY
        CalDate, InSession, stu_id, class
    ORDER BY
        stu_id, class, CalDate;
    

    Returns

    +------------+-----------+--------+---------+-------------+
    |  CalDate   | InSession | stu_id |  class  | absent_date |
    +------------+-----------+--------+---------+-------------+
    | 2020-11-02 |         1 | Billie | English |             |
    | 2020-11-03 |         1 | Billie | English | 11/03/2020  |
    | 2020-11-04 |         1 | Billie | English |             |
    | 2020-11-05 |         1 | Billie | English |             |
    | 2020-11-06 |         1 | Billie | English |             |
    | 2020-11-07 |         0 | Billie | English |             |
    | 2020-11-08 |         0 | Billie | English |             |
    | 2020-11-09 |         1 | Billie | English |             |
    | 2020-11-10 |         1 | Billie | English |             |
    | 2020-11-11 |         0 | Billie | English |             |
    | 2020-11-12 |         1 | Billie | English |             |
    | 2020-11-13 |         1 | Billie | English |             |
    | 2020-11-14 |         0 | Billie | English |             |
    | 2020-11-15 |         0 | Billie | English |             |
    | 2020-11-16 |         1 | Billie | English |             |
    | 2020-11-17 |         1 | Billie | English |             |
    | 2020-11-18 |         1 | Billie | English |             |
    | 2020-11-19 |         1 | Billie | English |             |
    | 2020-11-20 |         0 | Billie | English |             |
    | 2020-11-02 |         1 | Billie | Math    |             |
    | 2020-11-03 |         1 | Billie | Math    |             |
    | 2020-11-04 |         1 | Billie | Math    |             |
    | 2020-11-05 |         1 | Billie | Math    |             |
    | 2020-11-06 |         1 | Billie | Math    |             |
    | 2020-11-07 |         0 | Billie | Math    |             |
    | 2020-11-08 |         0 | Billie | Math    |             |
    | 2020-11-09 |         1 | Billie | Math    |             |
    | 2020-11-10 |         1 | Billie | Math    | 11/10/2020  |
    | 2020-11-11 |         0 | Billie | Math    |             |
    | 2020-11-12 |         1 | Billie | Math    | 11/12/2020  |
    | 2020-11-13 |         1 | Billie | Math    |             |
    | 2020-11-14 |         0 | Billie | Math    |             |
    | 2020-11-15 |         0 | Billie | Math    |             |
    | 2020-11-16 |         1 | Billie | Math    |             |
    | 2020-11-17 |         1 | Billie | Math    |             |
    | 2020-11-18 |         1 | Billie | Math    |             |
    | 2020-11-19 |         1 | Billie | Math    | 11/19/2020  |
    | 2020-11-20 |         0 | Billie | Math    |             |
    | 2020-11-02 |         1 | Billie | Science |             |
    | 2020-11-03 |         1 | Billie | Science |             |
    | 2020-11-04 |         1 | Billie | Science |             |
    | 2020-11-05 |         1 | Billie | Science |             |
    | 2020-11-06 |         1 | Billie | Science |             |
    | 2020-11-07 |         0 | Billie | Science |             |
    | 2020-11-08 |         0 | Billie | Science |             |
    | 2020-11-09 |         1 | Billie | Science |             |
    | 2020-11-10 |         1 | Billie | Science |             |
    | 2020-11-11 |         0 | Billie | Science |             |
    | 2020-11-12 |         1 | Billie | Science |             |
    | 2020-11-13 |         1 | Billie | Science |             |
    | 2020-11-14 |         0 | Billie | Science |             |
    | 2020-11-15 |         0 | Billie | Science |             |
    | 2020-11-16 |         1 | Billie | Science |             |
    | 2020-11-17 |         1 | Billie | Science |             |
    | 2020-11-18 |         1 | Billie | Science |             |
    | 2020-11-19 |         1 | Billie | Science | 11/19/2020  |
    | 2020-11-20 |         0 | Billie | Science |             |
    +------------+-----------+--------+---------+-------------+