英文:
How to get the overall count in a multiple selection system with ranking
问题
以下是用于获取所需结果表的MySQL查询:
CREATE OR REPLACE VIEW public.poll_results AS
SELECT
c.id AS collection_id,
o.id AS option_id,
IFNULL(f.first_count, 0) AS 1st_count,
IFNULL(s.second_count, 0) AS 2nd_count,
IFNULL(t.third_count, 0) AS 3rd_count
FROM
(SELECT DISTINCT collection_id FROM vote) c
CROSS JOIN
(SELECT DISTINCT option_id FROM option) o
LEFT JOIN
(SELECT
vote.collection_id,
vote.first_option_id,
count(*) AS first_count
FROM vote
GROUP BY vote.collection_id, vote.first_option_id) f
ON c.collection_id = f.collection_id AND o.option_id = f.first_option_id
LEFT JOIN
(SELECT
vote.collection_id,
vote.second_option_id,
count(*) AS second_count
FROM vote
GROUP BY vote.collection_id, vote.second_option_id) s
ON c.collection_id = s.collection_id AND o.option_id = s.second_option_id
LEFT JOIN
(SELECT
vote.collection_id,
vote.third_option_id,
count(*) AS third_count
FROM vote
GROUP BY vote.collection_id, vote.third_option_id) t
ON c.collection_id = t.collection_id AND o.option_id = t.third_option_id
ORDER BY collection_id, option_id;
这个查询创建了一个名为"poll_results"的视图,它包含了按集合和选项分组的投票计数信息,包括第一、第二和第三选择的计数。如果在某个组合中没有投票,则相应的计数为0。
英文:
I am designing a database for a web project in which I am trying to collect users' emotional feelings toward art collections. A hybrid dual list on the website allows users to select three options from 12 options and then rank the selected three as 1st, 2nd, and 3rd. There are 1000 data points in this project, which means there are 1000 distinct art collections for the users to vote on, each of the art collections has the same 12 options.
collection_poll
+-------+--------------------+
| id | collection_name |
+-------+--------------------+
| 1 | collection 1 |
| 2 | collection 2 |
| 3 | collection 3 |
| 4 | collection 4 |
| 5 | collection 5 |
| ... | ... |
+-------+--------------------+
option
+--------------------+--------------------+----------------+
| collection_id | option id | Text |
+--------------------+--------------------+----------------+
| 1 | 1 | Emotion 1 |
| 1 | 2 | Emotion 2 |
| 1 | 3 | Emotion 3 |
| 1 | 4 | Emotion 4 |
| 1 | 5 | Emotion 5 |
| 1 | 6 | Emotion 6 |
| 1 | 7 | Emotion 7 |
| 1 | 8 | Emotion 8 |
| 1 | 9 | Emotion 9 |
| 1 | 10 | Emotion 10 |
| 1 | 11 | Emotion 11 |
| 1 | 12 | Emotion 12 |
| 2 | 1 | Emotion 1 |
| 2 | 2 | Emotion 2 |
| 2 | 3 | Emotion 3 |
| 2 | 4 | Emotion 4 |
| 2 | 5 | Emotion 5 |
| ... | ... | ... |
+--------------------+--------------------+----------------|
vote
+--+-------+-------------+-------------+-------------+-------------+
|id|user_id|collection_id|1st_option_id|2nd_option_id|3rd_option_id|
+--+-------+-------------+-------------+-------------+-------------+
|1 | 1 | 1 | 1 | 8 | 12 |
|2 | 2 | 1 | 3 | 1 | 8 |
|3 | 3 | 1 | 1 | 8 | 3 |
|4 | 1 | 2 | 1 | 8 | 12 |
|5 | 2 | 2 | 3 | 12 | 8 |
|6 | 3 | 2 | 1 | 3 | 12 |
+--+-------+-------------+-------------+-------------+-------------+
This table records each vote and specifies which collection the user votes and the 1st, 2nd, and 3rd options the user ranks.
How do I use MySQL to get this table?
+---------------+-----------+-----------+-----------+-----------+
| collection_id | option_id | 1st_count | 2nd_count | 3rd_count |
+---------------+-----------+-----------+-----------+-----------+
| 1 | 1 | 2 | 1 | 0 |
| 1 | 2 | 0 | 0 | 0 |
| 1 | 3 | 1 | 0 | 1 |
| 1 | 4 | 0 | 0 | 0 |
| ... ... ... ... ... |
| 1 | 8 | 0 | 2 | 1 |
| ... ... ... ... ... |
| 1 | 12 | 0 | 0 | 1 |
| 2 | 1 | 2 | 0 | 0 |
| 2 | 2 | 0 | 0 | 0 |
| 2 | 3 | 1 | 1 | 0 |
| ... ... ... ... ... |
| 2 | 8 | 0 | 1 | 1 |
| ... ... ... ... ... |
| 2 | 12 | 0 | 1 | 2 |
| ... ... ... ... ... |
+---------------+-----------+-----------+-----------+-----------+
which uses collection_poll.id and option.id to get the result from table_vote.
I have
CREATE
OR REPLACE VIEW "public"."poll_results_first_option_count" AS
SELECT
vote.collection_id,
vote.first_option_id,
count(*) AS first_count
FROM
vote
GROUP BY
vote.collection_id,
vote.first_option_id
ORDER BY
vote.collection_id,
vote.first_option_id;
to get the count of each rank but cannot put them together.
答案1
得分: 0
Step 1: 做加法
SELECT collection_id,
1st_option_id,
COUNT(*) AS 1st_count
FROM votes
GROUP BY 1,2
以及对其他选项做类似的操作
Step 2: 将它们合并(有点像“旋转”):
SELECT collection_id,
1st_count,
2nd_count,
3rd_count
FROM ( ... ) AS t1
JOIN ( ... ) AS t2 USING(collection_id)
JOIN ( ... ) AS t3 USING(collection_id)
ORDER BY collection_id;
其中“...” 来自步骤1。
英文:
Step 1: Do the sums
SELECT collection_id,
1st_option_id,
COUNT(*) AS 1st_count
FROM votes
GROUP BY 1,2
and do similarly for the others
Step 2: Put them together (somewhat like "pivot"):
SELECT collection_id,
1st_count,
2nd_count,
3rd_count
FROM ( ... ) AS t1
JOIN ( ... ) AS t2 USING(collection_id)
JOIN ( ... ) AS t3 USING(collection_id)
ORDER BY collection_id;
where the "..." comes from step 1
答案2
得分: 0
接受的答案未提供正确的结果。您需要使用LEFT JOIN
,从您的option
表开始,并在连接条件中包括option_id
:
SELECT `o`.`collection_id`, `o`.`option_id`,
`1st_count`,
`2nd_count`,
`3rd_count`
FROM `option` `o`
LEFT JOIN ( SELECT `collection_id`, `1st_option_id` AS `option_id`, COUNT(*) AS `1st_count` FROM `vote` GROUP BY 1, 2 ) AS `t1` USING (`collection_id`, `option_id`)
LEFT JOIN ( SELECT `collection_id`, `2nd_option_id` AS `option_id`, COUNT(*) AS `2nd_count` FROM `vote` GROUP BY 1, 2 ) AS `t2` USING (`collection_id`, `option_id`)
LEFT JOIN ( SELECT `collection_id`, `3rd_option_id` AS `option_id`, COUNT(*) AS `3rd_count` FROM `vote` GROUP BY 1, 2 ) AS `t3` USING (`collection_id`, `option_id`)
ORDER BY `o`.`collection_id`, `o`.`option_id`;
在您的问题中,您提到:
>每个艺术收藏品都有相同的12个选项
如果是这样的话,那么在option
表中不需要将它们连接起来。相反,您可以只有这十二个选项(并且删除collection_id
列),然后与collection_poll
进行CROSS JOIN以构建完整的列表:
SELECT `cp`.`id`, `o`.`option_id`,
`1st_count`,
`2nd_count`,
`3rd_count`
FROM `collection_poll` `cp`
CROSS JOIN `option` `o`
LEFT JOIN ( SELECT `collection_id`, `1st_option_id` AS `option_id`, COUNT(*) AS `1st_count` FROM `vote` GROUP BY 1, 2 ) AS `t1` ON `cp`.`id` = `t1`.`collection_id` AND `o`.`option_id` = `t1`.`option_id`
LEFT JOIN ( SELECT `collection_id`, `2nd_option_id` AS `option_id`, COUNT(*) AS `2nd_count` FROM `vote` GROUP BY 1, 2 ) AS `t2` ON `cp`.`id` = `t2`.`collection_id` AND `o`.`option_id` = `t2`.`option_id`
LEFT JOIN ( SELECT `collection_id`, `3rd_option_id` AS `option_id`, COUNT(*) AS `3rd_count` FROM `vote` GROUP BY 1, 2 ) AS `t3` ON `cp`.`id` = `t3`.`collection_id` AND `o`.`option_id` = `t3`.`option_id`
ORDER BY cp.id, o.option_id;
英文:
The accepted answer does not provide the correct results. You need to be LEFT JOIN
ing, starting from your option
table and including option_id
in the JOIN criteria:
SELECT `o`.`collection_id`, `o`.`option_id`,
`1st_count`,
`2nd_count`,
`3rd_count`
FROM `option` `o`
LEFT JOIN ( SELECT `collection_id`, `1st_option_id` AS `option_id`, COUNT(*) AS `1st_count` FROM `vote` GROUP BY 1, 2 ) AS `t1` USING (`collection_id`, `option_id`)
LEFT JOIN ( SELECT `collection_id`, `2nd_option_id` AS `option_id`, COUNT(*) AS `2nd_count` FROM `vote` GROUP BY 1, 2 ) AS `t2` USING (`collection_id`, `option_id`)
LEFT JOIN ( SELECT `collection_id`, `3rd_option_id` AS `option_id`, COUNT(*) AS `3rd_count` FROM `vote` GROUP BY 1, 2 ) AS `t3` USING (`collection_id`, `option_id`)
ORDER BY `o`.`collection_id`, `o`.`option_id`;
In your question you state:
> each of the art collections has the same 12 options
If this is the case, then there is no need to link them in your option
table. Instead you can just have the twelve options (and drop collection_id
column) and CROSS JOIN to collection_poll
to build the full list:
SELECT `cp`.`id`, `o`.`option_id`,
`1st_count`,
`2nd_count`,
`3rd_count`
FROM `collection_poll` `cp`
CROSS JOIN `option` `o`
LEFT JOIN ( SELECT `collection_id`, `1st_option_id` AS `option_id`, COUNT(*) AS `1st_count` FROM `vote` GROUP BY 1, 2 ) AS `t1` ON `cp`.`id` = `t1`.`collection_id` AND `o`.`option_id` = `t1`.`option_id`
LEFT JOIN ( SELECT `collection_id`, `2nd_option_id` AS `option_id`, COUNT(*) AS `2nd_count` FROM `vote` GROUP BY 1, 2 ) AS `t2` ON `cp`.`id` = `t2`.`collection_id` AND `o`.`option_id` = `t2`.`option_id`
LEFT JOIN ( SELECT `collection_id`, `3rd_option_id` AS `option_id`, COUNT(*) AS `3rd_count` FROM `vote` GROUP BY 1, 2 ) AS `t3` ON `cp`.`id` = `t3`.`collection_id` AND `o`.`option_id` = `t3`.`option_id`
ORDER BY cp.id, o.option_id;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论