MySQL,根据大多数投票总结多行和排名

时间:2011-12-13 03:15:17

标签: php mysql

我有以下数据库

id  rank1   rank2   rank3   rank4
1   5       4       8       9
2   5       8       9       4
3   8       5       3       1
4   5       8       2       1
5   8       5       3       1
6   5       8       3       1

我需要一个mysql查询或php脚本来统计排名,并根据它在表格中出现的次数显示前4位...即。最终结果应该类似于:

rank1 = 5
rank2 = 8
rank3 = 3
rank4 = 1

任何想法???提前谢谢

2 个答案:

答案 0 :(得分:0)

你的桌面设计远非最佳,如果你没想到它之前你肯定会看到它,因为你意识到获得你所得到的结果的方法需要这个“不那么漂亮 “查询,虽然它有效。

SELECT name, rank FROM (
  (
    SELECT 'rank1' name, rank1 rank
    FROM foobar GROUP BY rank1
    ORDER BY count(*) DESC LIMIT 1
  ) rank1_foobar
)
UNION SELECT name, rank FROM (
  (
    SELECT 'rank2' name, rank2 rank
    FROM foobar GROUP BY rank2
    ORDER BY count(*) DESC LIMIT 1
  ) rank2_foobar
)
UNION SELECT name, rank FROM (
  (
    SELECT 'rank3' name, rank3 rank
    FROM foobar GROUP BY rank3
    ORDER BY count(*) DESC LIMIT 1
  ) rank3_foobar
)
UNION SELECT name, rank FROM (
  (
    SELECT 'rank4' name, rank4 rank
    FROM foobar GROUP BY rank4
    ORDER BY count(*) DESC LIMIT 1
  ) rank4_foobar
)

输出

+-------+------+
| name  | rank |
+-------+------+
| rank1 |    5 |
| rank2 |    8 |
| rank3 |    3 |
| rank4 |    1 |
+-------+------+

我会将您的表重组为如下所示,这样可以更轻松地将查询编写为您所请求的查询。

CREATE TABLE ranks (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  group_id INT UNSIGNED NOT NULL COMMENT 'to be able to group more than one row in `ranks` together',
  rank_type ENUM('rank1','rank2','rank3','rank4'),
  rank_value INT,
  PRIMARY KEY(`id`)
);

答案 1 :(得分:0)

由于数据规范化不佳,它不像单个select / from group by那么简单。您需要将每个“Rank”列作为union的一部分进行查询,然后将其向上滚动。为了保持临时临时值的减少,我们仍然可以预先对计数进行分组,这样您就不会运行所有行4次,而是在相应的组段中按照每个等级进行前贴片1次

select
      PreAgg.Rank,
      SUM( PreAgg.RankCount ) as TotalCount
   from 
      ( select
              YT.Rank1 as Rank,
              COUNT(*) as RankCount
           from 
              YourTable YT
           group by 
              YT.Rank1
        UNION ALL
        select
              YT.Rank2 as Rank,
              COUNT(*) as RankCount
           from 
              YourTable YT
           group by 
              YT.Rank2
        UNION ALL
        select
              YT.Rank3 as Rank,
              COUNT(*) as RankCount
           from 
              YourTable YT
           group by 
              YT.Rank3
        UNION ALL
        select
              YT.Rank4 as Rank,
              COUNT(*) as RankCount
           from 
              YourTable YT
           group by 
              YT.Rank4 ) PreAgg
   GROUP BY
      PreAgg.Rank,
      SUM( PreAgg.RankCount ) DESC

正如Ajreal所指出的那样,它需要对结构进行更多的澄清......有没有理由为什么你有4个不同的列都是“Rank”而不是更像规范化的表...

ID   RankGroup   Rank
1     1          5
2     1          5
3     1          8
4     1          5
5     1          8
6     1          5
7     2          4
7     2          8
7     2          5
7     2          8
7     2          5
7     2          8
etc for ranks 3 and 4

然后,无论“组级”条件如何,您都可以获得每个RANK的计数,或者在非常简化的查询中获得每组最佳排名。