如何在具有排名的多选系统中获取总计数

huangapple go评论56阅读模式
英文:

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 JOINing, 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;

huangapple
  • 本文由 发表于 2023年2月16日 14:15:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75468488.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定