Hacker Public Radio

HPR4378: SQL to get the next_free_slot


Listen Later

This show has been flagged as Clean by the host.

SQL for find next available Episode
Problem

https://repo.anhonesthost.net/HPR/hpr_hub/issues/71


We need to get the next_free_slot, and this needs to take into account the Eps and reservations table.
  • Eps table contain recorded and uploaded shows.
  • reservations table reserve episodes that have not been recorded.
  • There are existing queries to find the next free slot, but it does not include reservations.
  • HPR SQL dump
    -
    https://hackerpublicradio.org/hpr.sql

    TLDR
    • Create a list of all episode IDs from eps and reservations tables using SQL
      UNION
    • Join the union list + 1 with the IDs from the eps and reservation tables
    • WHERE clause to select rows in the union list +1 that are not in eps and not in reservations
    • Order by and Limit to select the smallest

      Test Data
      • Test data to make developing query easier.
      • Simpler numbers so it is easier to spot patterns
      • Same table and column names, and store them in a different database.
        Create the test data tables
        -- Create eps
        CREATE TABLE IF NOT EXISTS eps (
        id INT,
        PRIMARY KEY (id)
        );
        CREATE TABLE IF NOT EXISTS reservations (
        ep_num INT,
        PRIMARY KEY (ep_num)
        );
        Insert the test data
        -- Inserts
        INSERT INTO eps (id) VALUES (1001);
        INSERT INTO eps (id) VALUES (1002);
        INSERT INTO eps (id) VALUES (1003);
        INSERT INTO eps (id) VALUES (1004);
        INSERT INTO eps (id) VALUES (1011);
        INSERT INTO eps (id) VALUES (1021);
        INSERT INTO eps (id) VALUES (1031);
        INSERT INTO eps (id) VALUES (1041);
        INSERT INTO reservations (ep_num) VALUES (1004);
        INSERT INTO reservations (ep_num) VALUES (1005);
        INSERT INTO reservations (ep_num) VALUES (1006);
        INSERT INTO reservations (ep_num) VALUES (1010);
        INSERT INTO reservations (ep_num) VALUES (1016);
        Print the test data tables
        -- Episodes
        SELECT e.id as e_id FROM eps e order by e.id;
        +------+
        | e_id |
        +------+
        | 1001 |
        | 1002 |
        | 1003 |
        | 1004 |
        | 1011 |
        | 1021 |
        | 1031 |
        | 1041 |
        +------+
        SELECT r.ep_num as r_id FROM reservations r;
        +------+
        | r_id |
        +------+
        | 1004 |
        | 1005 |
        | 1006 |
        | 1010 |
        | 1016 |
        +------+

        Join Types
        • UNION - combine results of 2 queries
        • INNER - Only records that are in both tables
        • LEFT - All the Results in the Left column and matching results in the Right
          Test data Join Examples
          • In the test data, the ID
            1004
            is in both the episodes and reservations table.
          • This will not occur in the real HPR database, but is useful to how different join types work
          • Example queries with
            INNER
            ,
            RIGHT
            , and
            LEFT
            joins.
            MariaDB [next_av]> SELECT e.id ,r.ep_num FROM eps e INNER JOIN reservations r ON e.id = r.ep_num;
            +------+--------+
            | id | ep_num |
            +------+--------+
            | 1004 | 1004 |
            +------+--------+
            1 row in set (0.001 sec)
            MariaDB [next_av]> SELECT e.id ,r.ep_num FROM eps e RIGHT JOIN reservations r ON e.id = r.ep_num;
            +------+--------+
            | id | ep_num |
            +------+--------+
            | 1004 | 1004 |
            | NULL | 1005 |
            | NULL | 1006 |
            | NULL | 1010 |
            | NULL | 1016 |
            +------+--------+
            5 rows in set (0.001 sec)
            MariaDB [next_av]> SELECT e.id ,r.ep_num FROM eps e LEFT JOIN reservations r ON e.id = r.ep_num;
            +------+--------+
            | id | ep_num |
            +------+--------+
            | 1001 | NULL |
            | 1002 | NULL |
            | 1003 | NULL |
            | 1004 | 1004 |
            | 1011 | NULL |
            | 1021 | NULL |
            | 1031 | NULL |
            | 1041 | NULL |
            +------+--------+
            8 rows in set (0.001 sec)

            Combine episode and reserved IDs
            • Create a single list of IDs from both tables with
              UNION
            • UNION combines the results of 2 queries
            • SQL
              as
              keyword renames query results
              SELECT id as all_ids
              FROM eps
              UNION
              select ep_num FROM reservations
              ;
              +---------+
              | all_ids |
              +---------+
              | 1001 |
              | 1002 |
              | 1003 |
              | 1004 |
              | 1011 |
              | 1021 |
              | 1031 |
              | 1041 |
              | 1005 |
              | 1006 |
              | 1010 |
              | 1016 |
              +---------+

              Join tables with the Union
              • Left Joins Keep everything in the Left column
              • Use the Union of all IDs and join with Eps and reservations
              • The SQL will print a table of all the ids
              • the eps and reservation columns will have the id if they match or NULL if there is not a match.
                select all_ids.id as all_ids ,eps.id as eps_ids , r.ep_num as reserved_ids FROM
                (SELECT id
                FROM eps
                UNION
                select ep_num FROM reservations)
                as all_ids
                LEFT JOIN eps
                ON all_ids.id = eps.id
                LEFT JOIN reservations r
                ON all_ids.id = r.ep_num
                ;
                +---------+---------+--------------+
                | all_ids | eps_ids | reserved_ids |
                +---------+---------+--------------+
                | 1001 | 1001 | NULL |
                | 1002 | 1002 | NULL |
                | 1003 | 1003 | NULL |
                | 1004 | 1004 | 1004 |
                | 1011 | 1011 | NULL |
                | 1021 | 1021 | NULL |
                | 1031 | 1031 | NULL |
                | 1041 | 1041 | NULL |
                | 1005 | NULL | 1005 |
                | 1006 | NULL | 1006 |
                | 1010 | NULL | 1010 |
                | 1016 | NULL | 1016 |
                +---------+---------+--------------+

                Join with union plus 1 -- All Results
                • Add an additional column of the union ids +1
                • Join the Union plus one list with the episodes and reservations
                • Available episodes will have NULL in the eps and reservations column
                  select all_ids.id as all_ids,all_ids.id+1 as all_ids_plus ,eps.id as eps_ids , r.ep_num as reserved_ids FROM
                  (SELECT id
                  FROM eps
                  UNION
                  select ep_num FROM reservations)
                  as all_ids
                  LEFT JOIN eps
                  ON all_ids.id+1 = eps.id
                  LEFT JOIN reservations r
                  ON all_ids.id +1 = r.ep_num
                  ORDER BY all_ids
                  ;
                  +---------+--------------+---------+--------------+
                  | all_ids | all_ids_plus | eps_ids | reserved_ids |
                  +---------+--------------+---------+--------------+
                  | 1001 | 1002 | 1002 | NULL |
                  | 1002 | 1003 | 1003 | NULL |
                  | 1003 | 1004 | 1004 | 1004 |
                  | 1004 | 1005 | NULL | 1005 |
                  | 1005 | 1006 | NULL | 1006 |
                  | 1006 | 1007 | NULL | NULL |
                  | 1010 | 1011 | 1011 | NULL |
                  | 1011 | 1012 | NULL | NULL |
                  | 1016 | 1017 | NULL | NULL |
                  | 1021 | 1022 | NULL | NULL |
                  | 1031 | 1032 | NULL | NULL |
                  | 1041 | 1042 | NULL | NULL |
                  +---------+--------------+---------+--------------+

                  Add a WHERE clause
                  • Add a where clause to only print rows were eps and reservations are null
                  • The smallest number in the +1 column will be the next available
                    select all_ids.id as all_ids,all_ids.id+1 as all_ids_plus ,eps.id as eps_ids , r.ep_num as reserved_ids FROM
                    (SELECT id
                    FROM eps
                    UNION
                    select ep_num FROM reservations)
                    as all_ids
                    LEFT JOIN eps
                    ON all_ids.id+1 = eps.id
                    LEFT JOIN reservations r
                    ON all_ids.id +1 = r.ep_num
                    WHERE eps.id is Null and r.ep_num is NULL
                    ORDER BY all_ids
                    ;
                    +---------+--------------+---------+--------------+
                    | all_ids | all_ids_plus | eps_ids | reserved_ids |
                    +---------+--------------+---------+--------------+
                    | 1006 | 1007 | NULL | NULL |
                    | 1011 | 1012 | NULL | NULL |
                    | 1016 | 1017 | NULL | NULL |
                    | 1021 | 1022 | NULL | NULL |
                    | 1031 | 1032 | NULL | NULL |
                    | 1041 | 1042 | NULL | NULL |
                    +---------+--------------+---------+--------------+
                    6 rows in set (0.002 sec)

                    Add a limit and only select the id
                    • Sort and select the 1st row
                      select all_ids.id+1 as available_id FROM
                      (SELECT id
                      FROM eps
                      UNION
                      select ep_num FROM reservations)
                      as all_ids
                      LEFT JOIN eps
                      ON all_ids.id+1 = eps.id
                      LEFT JOIN reservations r
                      ON all_ids.id +1 = r.ep_num
                      WHERE eps.id is Null and r.ep_num is NULL
                      ORDER BY available_id
                      LIMIT 1
                      ;
                      +--------------+
                      | available_id |
                      +--------------+
                      | 1007 |
                      +--------------+


                      Provide feedback on this episode.

                      ...more
                      View all episodesView all episodes
                      Download on the App Store

                      Hacker Public RadioBy Hacker Public Radio

                      • 4.2
                      • 4.2
                      • 4.2
                      • 4.2
                      • 4.2

                      4.2

                      34 ratings


                      More shows like Hacker Public Radio

                      View all
                      The Infinite Monkey Cage by BBC Radio 4

                      The Infinite Monkey Cage

                      1,960 Listeners

                      Click Here by Recorded Future News

                      Click Here

                      419 Listeners

                      Hacker And The Fed by Chris Tarbell & Hector Monsegur

                      Hacker And The Fed

                      167 Listeners