Site Map - skip to main content

Hacker Public Radio

Your ideas, projects, opinions - podcasted.

New episodes every weekday Monday through Friday.
This page was generated by The HPR Robot at


hpr4378 :: SQL to get the next_free_slot

norrist talks about SQL to find the next available HPR slot

<< First, < Previous, Next > Latest >>

Hosted by norrist on Wednesday, 2025-05-14 is flagged as Clean and is released under a CC-BY-SA license.
sql, hpr. (Be the first).

Listen in ogg, opus, or mp3 format. Play now:

Duration: 00:28:26
Download the transcription and subtitles.

general.

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 |
+--------------+



Comments

Subscribe to the comments RSS feed.

Leave Comment

Note to Verbose Commenters
If you can't fit everything you want to say in the comment below then you really should record a response show instead.

Note to Spammers
All comments are moderated. All links are checked by humans. We strip out all html. Feel free to record a show about yourself, or your industry, or any other topic we may find interesting. We also check shows for spam :).

Provide feedback
Your Name/Handle:
Title:
Comment:
Anti Spam Question: What does the letter P in HPR stand for?
Are you a spammer?
Who is the host of this show?
What does HPR mean to you?