如何统计分3列存储的各电影流派数量?适配Tableau可视化需求
解决方法
核心思路是将分散在多列的流派数据**逆透视(Unpivot)**为单行单流派的结构,之后再按年份和流派分组统计,这种方式比嵌套CASE语句简洁得多,维护性也更好。以下分SQL查询和Tableau直接处理两种场景说明:
一、SQL查询方案
通用SQL(适用于所有数据库)
用UNION ALL拆分三个流派列,过滤空值后分组统计,这是最兼容的写法:
SELECT year, genre, COUNT(*) AS film_count FROM ( -- 取出第一列流派,排除空值 SELECT year, genre1 AS genre FROM movies WHERE genre1 IS NOT NULL -- 合并第二列流派 UNION ALL SELECT year, genre2 AS genre FROM movies WHERE genre2 IS NOT NULL -- 合并第三列流派 UNION ALL SELECT year, genre3 AS genre FROM movies WHERE genre3 IS NOT NULL ) AS unpivoted_genres GROUP BY year, genre ORDER BY year, film_count DESC;
各数据库专属优化写法
PostgreSQL
利用UNNEST将流派列转为数组后展开:
SELECT year, genre, COUNT(*) AS film_count FROM movies, UNNEST(ARRAY[genre1, genre2, genre3]) AS genre WHERE genre IS NOT NULL GROUP BY year, genre ORDER BY year, film_count DESC;
SQL Server
使用内置UNPIVOT操作符:
SELECT year, genre, COUNT(*) AS film_count FROM movies UNPIVOT ( genre FOR genres IN (genre1, genre2, genre3) ) AS unpivoted_data WHERE genre IS NOT NULL GROUP BY year, genre ORDER BY year, film_count DESC;
MySQL 8.0+/MariaDB
用LATERAL JOIN实现逆透视:
SELECT m.year, g.genre, COUNT(*) AS film_count FROM movies m JOIN LATERAL ( SELECT genre1 AS genre UNION ALL SELECT genre2 AS genre UNION ALL SELECT genre3 AS genre ) g ON g.genre IS NOT NULL GROUP BY m.year, g.genre ORDER BY m.year, film_count DESC;
二、Tableau直接处理(无需额外SQL)
如果不想写查询语句,可直接在Tableau中完成数据转换:
- 连接数据库后,选中
genre1、genre2、genre3三列 - 右键点击选中的列,选择逆透视(Unpivot)
- 将自动生成的
Pivot Field Values列重命名为「流派」,过滤掉该列的NULL值 - 将「年份」拖至行功能区,「流派」拖至列功能区,再将电影标题(或记录数)拖至标记卡的「文本/大小」,即可生成各年份流派数量的可视化图表。
内容的提问来源于stack exchange,提问作者cafxne
相关产品推荐
相关产品推荐

