-- 051_stats_views.sql -- Database Views for Common Queries (BE-DB-013: Add database views for common queries) -- Create views for user_stats, track_stats, playlist_stats -- === USER_STATS VIEW === -- View for user statistics aggregating data from multiple tables CREATE OR REPLACE VIEW public.user_stats AS SELECT u.id AS user_id, u.username, u.email, u.created_at AS user_created_at, -- Track statistics COUNT(DISTINCT t.id) AS tracks_count, COALESCE(SUM(t.play_count), 0) AS total_track_plays, COALESCE(SUM(t.like_count), 0) AS total_track_likes, COALESCE(SUM(t.download_count), 0) AS total_track_downloads, -- Playlist statistics COUNT(DISTINCT p.id) AS playlists_count, COALESCE(SUM(p.track_count), 0) AS total_playlist_tracks, COALESCE(SUM(p.follower_count), 0) AS total_playlist_followers, -- Social statistics COUNT(DISTINCT f1.id) AS followers_count, COUNT(DISTINCT f2.id) AS following_count, -- Playback statistics COUNT(DISTINCT tp.track_id) AS unique_tracks_played, COUNT(tp.id) AS total_plays, COALESCE(SUM(tp.duration), 0) AS total_play_duration, CASE WHEN COUNT(tp.id) > 0 THEN COALESCE(SUM(tp.duration), 0)::FLOAT / COUNT(tp.id) ELSE 0 END AS average_play_duration, -- Like statistics COUNT(DISTINCT tl.track_id) AS liked_tracks_count, -- Comment statistics COUNT(DISTINCT tc.id) AS comments_count FROM public.users u LEFT JOIN public.tracks t ON t.creator_id = u.id AND t.deleted_at IS NULL LEFT JOIN public.playlists p ON p.user_id = u.id AND p.deleted_at IS NULL LEFT JOIN public.follows f1 ON f1.followed_id = u.id LEFT JOIN public.follows f2 ON f2.follower_id = u.id LEFT JOIN public.track_plays tp ON tp.user_id = u.id LEFT JOIN public.track_likes tl ON tl.user_id = u.id LEFT JOIN public.track_comments tc ON tc.user_id = u.id AND tc.deleted_at IS NULL WHERE u.deleted_at IS NULL GROUP BY u.id, u.username, u.email, u.created_at; COMMENT ON VIEW public.user_stats IS 'Aggregated user statistics view including tracks, playlists, social, and playback metrics'; -- === TRACK_STATS VIEW === -- View for track statistics aggregating plays, likes, comments, and downloads CREATE OR REPLACE VIEW public.track_stats AS SELECT t.id AS track_id, t.title, t.artist, t.creator_id, t.created_at AS track_created_at, t.published_at, -- Denormalized counts from tracks table t.play_count AS views, t.like_count AS likes, t.comment_count AS comments, t.download_count AS downloads, -- Playback statistics COUNT(DISTINCT tp.user_id) AS unique_listeners, COUNT(tp.id) AS total_plays, COALESCE(SUM(tp.duration), 0) AS total_play_time, CASE WHEN COUNT(tp.id) > 0 THEN COALESCE(SUM(tp.duration), 0)::FLOAT / COUNT(tp.id) ELSE 0 END AS average_duration, -- Share statistics COUNT(DISTINCT ts.id) AS share_links_count, COALESCE(SUM(ts.access_count), 0) AS total_share_accesses FROM public.tracks t LEFT JOIN public.track_plays tp ON tp.track_id = t.id LEFT JOIN public.track_shares ts ON ts.track_id = t.id AND ts.deleted_at IS NULL WHERE t.deleted_at IS NULL GROUP BY t.id, t.title, t.artist, t.creator_id, t.created_at, t.published_at, t.play_count, t.like_count, t.comment_count, t.download_count; COMMENT ON VIEW public.track_stats IS 'Aggregated track statistics view including plays, likes, comments, and downloads'; -- === PLAYLIST_STATS VIEW === -- View for playlist statistics aggregating tracks, followers, and plays CREATE OR REPLACE VIEW public.playlist_stats AS SELECT p.id AS playlist_id, p.name AS playlist_name, p.user_id AS creator_id, p.created_at AS playlist_created_at, p.updated_at AS playlist_updated_at, -- Denormalized counts from playlists table p.track_count AS tracks_count, p.follower_count AS followers_count, -- Track statistics (aggregated from playlist_tracks) COUNT(DISTINCT pt.track_id) AS actual_track_count, COALESCE(SUM(t.play_count), 0) AS total_track_plays, COALESCE(SUM(t.like_count), 0) AS total_track_likes, COALESCE(AVG(t.duration), 0) AS average_track_duration, COALESCE(SUM(t.duration), 0) AS total_playlist_duration, -- Collaboration statistics COUNT(DISTINCT pc.user_id) AS collaborators_count, -- Share statistics COUNT(DISTINCT psl.id) AS share_links_count, COALESCE(SUM(psl.access_count), 0) AS total_share_accesses FROM public.playlists p LEFT JOIN public.playlist_tracks pt ON pt.playlist_id = p.id LEFT JOIN public.tracks t ON t.id = pt.track_id AND t.deleted_at IS NULL LEFT JOIN public.playlist_collaborators pc ON pc.playlist_id = p.id AND pc.deleted_at IS NULL LEFT JOIN public.playlist_share_links psl ON psl.playlist_id = p.id AND psl.deleted_at IS NULL WHERE p.deleted_at IS NULL GROUP BY p.id, p.name, p.user_id, p.created_at, p.updated_at, p.track_count, p.follower_count; COMMENT ON VIEW public.playlist_stats IS 'Aggregated playlist statistics view including tracks, followers, plays, and collaboration metrics'; -- Indexes for better query performance (if needed) -- Note: Views don't support indexes directly, but indexes on underlying tables will help