I've built a program that converts an Excel sheet containing my departments schedule to a SQL table. We always work in pairs so I want to be able to check all my shifts and what person I'll be working with for those shifts.
Table structure is, where T, K and N are the different shifts:
Week | Date | Jim | Chad | Ernest | Rogier |
---|---|---|---|---|---|
10 | 2025-04-14 | T | K | N | T |
10 | 2025-04-15 | K | K | N | T |
10 | 2025-04-16 | N | K | N | T |
10 | 2025-04-17 | N | K | N | T |
If I'm Jim in the table above I want to be able to get a response for 2025-04-14 like:
Week | Date | Jim | Rogier |
---|---|---|---|
10 | 2025-04-14 | T | T |
And for 2025-04-15 like:
Week | Date | Jim | Chad |
---|---|---|---|
10 | 2025-04-15 | K | K |
I honestly have no idea how to do something like this. I've only done very basic SQL queries before, like finding all rows where the X equals Y.
SQL isn't really geared to dynamically handling columns.
One approach suggested in the comments is to show null
s for the people that don't share a shift with Jim, using a case
expression
SELECT week, date, jim,
CASE chad WHEN jim THEN chad END,
CASE ernest WHEN jim THEN ernest END,
CASE rogier WHEN jim THEN rogier END
FROM shifts
A slightly nicer (IMHO) solution is to use a case
expression to display the name of the person sharing a shift with Jim:
SELECT week, date, jim,
CASE jim
WHEN chad THEN 'Chad'
WHEN ernest THEN 'Ernest'
WHEN rogier THEN 'Rogier'
END
FROM shifts
But ultimately, both of these are workarounds for a table design that isn't sufficiently normalized.
A more idiomatic approach would be to have a row in the table for each person's shift (i.e., your columns would be week
, date
, shift
and name
), and then self-join the table:
SELECT j.week, j.date, j.shift, o.name AS who_is_with_jim
FROM shifts j
LEFT JOIN shifts o ON j.week = o.week AND
j.date = o.date AND
j.shift = o.shift AND
j.name = 'Jim' AND
o.name != 'Jim'