假设我有这张表,假设用户(“投票者”)对各种对象(例如地点、网站、答案等,“投票者”)的评分介于 1 到 5 星之间(“分数”)。这个问题的更通用版本询问如何为一对 N foos 做什么。
mysql> SHOW CREATE TABLE scores;
CREATE TABLE `scores` (
`voter_id` BIGINT NOT NULL DEFAULT '0',
`votee_id` BIGINT NOT NULL DEFAULT '0',
`score` tinyint NOT NULL,
PRIMARY KEY (`voter_id`,`votee_id`),
KEY `votee_index` (`votee_id`)
);
我想为每个被投票者对象构建一个 .csv 文件,其中的列表示该对象已获得的一星、二星、三星、四星和五星票的数量,例如
output.csv:
votee_id, count_ones, count_twos, count_threes, count_fours, count_fives
1, 3, 7, 5, 3, 2
...
我知道我可以使用以下查询获取原始数据来支持此表:
SELECT votee_id, score, COUNT(score)
FROM scores
GROUP BY votee_id, score;
这并没有给我我想要的 csv 格式的数据:
对于给定对象未看到的分数,它不会列出 0。
它不会将对象的所有五个分数组合成一行/行(即,对数据进行非规范化/直方图)。
我想只使用 mysql 创建输出。
在闲逛了一段时间后,我有以下查询,它有效;但它的效率很低,我找不到/做任何更优雅的东西:
SELECT votee_id, GROUP_CONCAT(COALESCE(score_count, '0') ORDER BY AllUserCrossScore.score ASC)
FROM
(SELECT votee_id, score FROM
(SELECT 1 AS score UNION ALL
SELECT 2 AS score UNION ALL
SELECT 3 AS score UNION ALL
SELECT 4 AS score UNION ALL
SELECT 5 AS score) ScoresEnum
JOIN
(SELECT DISTINCT votee_id FROM scores) DistinctIds
) AllUserCrossScore
LEFT JOIN
(SELECT votee_id, score, COUNT(score) as score_count
FROM scores
GROUP BY votee_id, score
) ScoreCounts
USING (votee_id, score)
GROUP BY votee_id;
特别是,这感觉特别 hacky,因为我使用 GROUP_CONCAT 和 ',' 将分数放在一起;然后在其他地方摆弄让mysql也用','加入所有其他字段,从而为.csv产生正确的格式(摆弄未显示)。
在这种情况下,我怎样才能做得更好?