Bloc A - Code mort: - Suppression Studio (components, views, features) - Suppression gamification + services mock (projectService, storageService, gamificationService) - Mise à jour Sidebar, Navbar, locales Bloc B - Frontend: - Suppression modal.tsx deprecated, Modal.stories (doublon Dialog) - Feature flags: PLAYLIST_SEARCH, PLAYLIST_RECOMMENDATIONS, ROLE_MANAGEMENT = true - Suppression 19 tests orphelins, retrait exclusions vitest.config Bloc C - Backend: - Extraction routes_auth.go depuis router.go Bloc D - Rust: - Suppression security_legacy.rs (code mort, patterns déjà dans security/)
137 lines
5.2 KiB
SQL
137 lines
5.2 KiB
SQL
-- 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
|
|
|