3ef560e414
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.
30 lines
1.1 KiB
SQL
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'
|
|
);
|