如何用PostgreSQL生成DVD租赁每月最热门类别汇总表?
解决DVD租赁数据库每月热门类别统计问题
核心高效方案(避免循环)
SQL是声明式语言,循环属于过程式写法,不仅代码冗余易出错,性能也远不如纯聚合查询。推荐用窗口函数+条件聚合的组合,一步生成目标汇总表,具体分三步:
步骤1:统计每月各品类租赁数据
先按月份和类别分组,计算每个品类的租赁量,同时算出当月总租赁数:
WITH monthly_category_stats AS ( SELECT rental_month, category, COUNT(rental_id) AS category_rentals, SUM(COUNT(rental_id)) OVER (PARTITION BY rental_month) AS total_monthly_rentals FROM rental_details GROUP BY rental_month, category )
步骤2:筛选每月热门类别
用子查询定位每个月租赁量最高的品类,支持多个品类并列第一的场景:
, top_categories AS ( SELECT rental_month, -- 并列品类用逗号分隔,不同数据库对应函数:MySQL用GROUP_CONCAT,SQL Server用STRING_AGG STRING_AGG(category, ', ') AS top_category, category_rentals, total_monthly_rentals FROM monthly_category_stats WHERE (rental_month, category_rentals) IN ( SELECT rental_month, MAX(category_rentals) FROM monthly_category_stats GROUP BY rental_month ) GROUP BY rental_month, category_rentals, total_monthly_rentals )
步骤3:转成12列的汇总表
用条件聚合把行数据转成列,直接输出你需要的结构:
SELECT MAX(CASE WHEN rental_month = 1 THEN top_category END) AS "1月_热门类别", MAX(CASE WHEN rental_month = 1 THEN total_monthly_rentals END) AS "1月_总租赁数", MAX(CASE WHEN rental_month = 1 THEN category_rentals END) AS "1月_热门类别租赁数", MAX(CASE WHEN rental_month = 2 THEN top_category END) AS "2月_热门类别", MAX(CASE WHEN rental_month = 2 THEN total_monthly_rentals END) AS "2月_总租赁数", MAX(CASE WHEN rental_month = 2 THEN category_rentals END) AS "2月_热门类别租赁数", -- 重复上述结构,补全3-11月的字段 MAX(CASE WHEN rental_month = 12 THEN top_category END) AS "12月_热门类别", MAX(CASE WHEN rental_month = 12 THEN total_monthly_rentals END) AS "12月_总租赁数", MAX(CASE WHEN rental_month = 12 THEN category_rentals END) AS "12月_热门类别租赁数" FROM top_categories;
循环方案易出问题的原因
如果用数据库存储过程写循环,需要手动处理变量、结果集拼接,不仅代码繁琐,还容易因月份边界、空值处理等细节报错。而上述纯SQL方案,数据库会自动优化执行计划,性能和可维护性都更优。
内容的提问来源于stack exchange,提问作者ThatOnePerson1029
相关产品推荐
相关产品推荐

