We have a wages table holding wage rates by waiter and startdate, and a tips table which tracks hours worked and tips received per waiter per day. The requirement is to report wages and concurrent tips per waiter per day.
DROP TABLE IF EXISTS wages,tips; CREATE TABLE wages( id int, waiter int, start date, rate decimal(6,2)); INSERT INTO wages VALUES ( 1, 4, '2025-01-01', 5.00 ), ( 2, 4, '2025-03-01', 6.00 ), ( 3, 5, '2025-01-05', 7.00 ), ( 4, 5, '2024-03-20', 8.00 ), ( 5, 5, '2024-04-01', 9.00 ); CREATE TABLE tips( id int, date date, waiter int, hours_worked smallint, tabs smallint, tips decimal(6,2) ); INSERT INTO tips VALUES ( 1, '2025-02-29', 4, 6.50, 21, 65.25 ), ( 2, '2025-03-06', 5, 6.00, 15, 51.75 ), ( 3, '2024-03-21', 4, 2.50, 5, 17.85 ), ( 4, '2024-03-22', 5, 5.25, 10, 39.00 ); SELECT * FROM wages; +------+--------+------------+------+ | id | waiter | start | rate | +------+--------+------------+------+ | 1 | 4 | 2025-01-01 | 5.00 | | 2 | 4 | 2025-03-01 | 6.00 | | 3 | 5 | 2025-01-05 | 7.00 | | 4 | 5 | 2024-03-20 | 8.00 | | 5 | 5 | 2024-04-01 | 9.00 | +------+--------+------------+------+ SELECT * FROM tips; +------+------------+--------+--------------+------+-------+ | id | date | waiter | hours_worked | tabs | tips | +------+------------+--------+--------------+------+-------+ | 1 | 2025-02-29 | 4 | 7 | 21 | 65.25 | | 2 | 2025-03-06 | 5 | 6 | 15 | 51.75 | | 3 | 2024-03-21 | 4 | 3 | 5 | 17.85 | | 4 | 2024-03-22 | 5 | 5 | 10 | 39.00 | +------+------------+--------+--------------+------+-------+For the above dataset, the result which correctly matches wages and tips would be: +------+------------+------+------+-------+------+--------+------+------------+ | tid | Date | Hrs | tabs | tips | wid | waiter | rate | start | +------+------------+------+------+-------+------+--------+------+------------+ | 1 | 2025-02-29 | 7 | 21 | 65.25 | 2 | 4 | 6.00 | 2025-03-01 | | 2 | 2025-03-06 | 6 | 15 | 51.75 | 3 | 5 | 7.00 | 2025-01-05 | | 3 | 2024-03-21 | 3 | 5 | 17.85 | 2 | 4 | 6.00 | 2025-03-01 | | 4 | 2024-03-22 | 5 | 10 | 39.00 | 4 | 5 | 8.00 | 2024-03-20 | +------+------------+------+------+-------+------+--------+------+------------+Why is this different from an ordinary within-groups aggregate? The correct wage rate for a tips row is not the wages row for that waiter with the latest date; it is the wages row having the latest date before the date in the given tips row. One way to proceed is to build a temporary table from a join of wages to tips on waiter and -- wages-tips join removing later wage changes: DROP TABLE IF EXISTS tmp; CREATE TABLE tmp SELECT t.id AS tid, t.date AS Date, t.hours_worked AS Hrs,t.tabs,t.tips, w.id AS wid, w.waiter, w.rate, w.start FROM tips t JOIN wages w ON w.waiter=t.waiter AND w.start<=t.date; -- self-exclusion join to remove obsolete wage rows: SELECT t1.* FROM tmp t1 LEFT JOIN tmp t2 ON t1.tid=t2.tid and t1.start |