Files
minstrel/internal/db/queries/recommendation.sql
T
bvandeusen 3ef560e414 feat(db): add LoadRadioCandidates query
Single SELECT that joins tracks with general_likes (for is_liked) and
an aggregated LATERAL subquery on play_events (for last_played_at,
play_count, skip_count). Excludes seed + tracks played in the last
N hours. Drives the M3 weighted shuffle scoring.
2026-04-27 08:01:50 -04:00

30 lines
1.1 KiB
SQL

-- name: LoadRadioCandidates :many
-- Returns all tracks except the seed and any played by the user within
-- the last $3 hours, joined with the stats needed for scoring:
-- is_liked — boolean from general_likes for this user
-- last_played_at — max(play_events.started_at) for this user/track
-- play_count — count of play_events for this user/track
-- skip_count — play_events where was_skipped=true
SELECT
sqlc.embed(t),
(l.user_id IS NOT NULL)::bool AS is_liked,
pe.last_played_at::timestamptz AS last_played_at,
pe.play_count,
pe.skip_count
FROM tracks t
LEFT JOIN general_likes l ON l.user_id = $1 AND l.track_id = t.id
LEFT JOIN LATERAL (
SELECT
max(started_at) AS last_played_at,
count(*) AS play_count,
count(*) FILTER (WHERE was_skipped) AS skip_count
FROM play_events
WHERE user_id = $1 AND track_id = t.id
) pe ON true
WHERE t.id <> $2
AND NOT EXISTS (
SELECT 1 FROM play_events
WHERE user_id = $1 AND track_id = t.id
AND started_at > now() - $3 * interval '1 hour'
);