Mysql 如何对一组有限的可能值进行反规范化/直方图化输出?
假设我有这张表,假设代表用户(“选民”)对各种对象(如地点、网站、答案等,“选民”)的评级介于一到五星之间(“分数”)。这个问题的更一般的版本是问一对N foos应该做什么Mysql 如何对一组有限的可能值进行反规范化/直方图化输出?,mysql,Mysql,假设我有这张表,假设代表用户(“选民”)对各种对象(如地点、网站、答案等,“选民”)的评级介于一到五星之间(“分数”)。这个问题的更一般的版本是问一对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` tin
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`)
);
我想为每个votee对象构建一个.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格式的数据,我想:
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;
特别是,这让我感觉特别不舒服,因为我使用带有“,”的GROUP_CONCAT将分数组合在一起;然后在别处摆弄,让mysql也用“,”连接所有其他字段,从而为.csv生成正确的格式(摆弄未显示)
在这样的情况下,我怎样才能做得更好?我想你在寻找这样的东西:
SELECT
votee_id
SUM(CASE WHEN score = 1 THEN 1 ELSE 0 END) as count_ones
SUM(CASE WHEN score = 2 THEN 1 ELSE 0 END) as count_twos
SUM(CASE WHEN score = 3 THEN 1 ELSE 0 END) as count_threes
SUM(CASE WHEN score = 4 THEN 1 ELSE 0 END) as count_fours
SUM(CASE WHEN score = 5 THEN 1 ELSE 0 END) as count_fives
FROM scores
GROUP BY votee_id
我想你正在寻找这样的东西:
SELECT
votee_id
SUM(CASE WHEN score = 1 THEN 1 ELSE 0 END) as count_ones
SUM(CASE WHEN score = 2 THEN 1 ELSE 0 END) as count_twos
SUM(CASE WHEN score = 3 THEN 1 ELSE 0 END) as count_threes
SUM(CASE WHEN score = 4 THEN 1 ELSE 0 END) as count_fours
SUM(CASE WHEN score = 5 THEN 1 ELSE 0 END) as count_fives
FROM scores
GROUP BY votee_id
包装您的原始SQL
SELECT
votee_id AS votee_id,
SUM(IF(score=1,count_score,0)) AS count_ones,
SUM(IF(score=2,count_score,0)) AS count_twos,
SUM(IF(score=3,count_score,0)) AS count_threes,
SUM(IF(score=4,count_score,0)) AS count_fours,
SUM(IF(score=5,count_score,0)) AS count_fives
FROM (
SELECT votee_id, score, COUNT(score) as count_score
FROM scores
GROUP BY votee_id, score
) AS baseview
GROUP BY votee_id;
包装您的原始SQL
SELECT
votee_id AS votee_id,
SUM(IF(score=1,count_score,0)) AS count_ones,
SUM(IF(score=2,count_score,0)) AS count_twos,
SUM(IF(score=3,count_score,0)) AS count_threes,
SUM(IF(score=4,count_score,0)) AS count_fours,
SUM(IF(score=5,count_score,0)) AS count_fives
FROM (
SELECT votee_id, score, COUNT(score) as count_score
FROM scores
GROUP BY votee_id, score
) AS baseview
GROUP BY votee_id;
这肯定是一个更一般的答案,这使它成为我将记住的答案,尽管对于手头的特定问题,我认为Eric的答案更快,因为它避免了子选择。这肯定是一个更一般的答案,这使它成为我将记住的答案,虽然对于手头的特定问题,我认为Eric的答案更快,因为它避免了子选择。