SQL查询返回最受欢迎的颜色投票

时间:2014-04-15 07:24:27

标签: mysql sql ruby-on-rails ruby database

我们正在创建一个包含以下表格的投票系统:

Color: id, name
Panel: id, name
Votes: id, color_id, panel_id

我们正在努力定义正确的查询以获得每个面板投票最多的颜色。

目前我们正在循环遍历所有面板(在Ruby中)并执行以下SQL查询:

select colors.name, count(colors.name) as count 
from votes 
join colors on colors.id = votes.renderable_id 
where panel_id = X 
group by colors.name 
order by count desc 
limit 1;

返回以下信息:

name | count 
-----+-------
red  |    34

我们希望通过对panel_id进行分组来优化并在查询中包含面板,这样我们就不需要遍历所有面板了。我们的第一次尝试就是:

select votes.panel_id, colors.name, count(colors.name) as count 
from votes 
join colors on colors.id = votes.renderable_id 
group by votes.panel_id, colors.name;

返回

panel_id | name | count 
---------+------+-------
       8 | blue |    52
       5 | blue |    14
       8 | red  |    34

我们还希望删除panel_id的重复项,并选择max(count)。我们不能让这个工作?

是否有SQL专家可以帮助我们将其实现为单个SQL查询?我们已经感谢您的努力。

3 个答案:

答案 0 :(得分:0)

试试这个

select panel_id, max(count) as count
from ( 
     select votes.panel_id, colors.name, count(colors.name) as count 
     from votes 
     join colors on colors.id = votes.renderable_id 
     group by votes.panel_id, colors.name
     ) src
group by panel_id

答案 1 :(得分:0)

如果您不需要面板和颜色名称,则只能使用一个表(这也是最快的解决方案):

SELECT panel_id, color_id, MAX(votes) FROM (
  SELECT panel_id, color_id, COUNT(id) AS votes 
  FROM votes
  GROUP BY panel_id, color_id;
) t1

如果你需要名字,那就非常相似:

SELECT panel_id, panel_name, color_id, color_name, MAX(votes) FROM (
  SELECT panel_id, panel.name AS panel_name, color_id, color.name AS color_name, COUNT(id) AS votes 
  FROM votes
  LEFT JOIN panel ON panel.id = votes.panel_id
  LEFT JOIN color ON color.id = votes.color_id
  GROUP BY panel_id, color_id;
) t1

答案 2 :(得分:0)

这是MySQL不支持的窗口函数的典型案例。因此,我们使用group_concat来列出按投票排序的每个面板的所有颜色,并删除第一个。

select best_votes.panel_id, colors.name, best_votes.maxcnt
from
(
  select 
    panel_id, 
    max(cnt) as maxcnt,
    substring_index(concat(group_concat(color_id order by cnt desc separator ','), ','), ',', 1) as maxcolor
  from
  (
    select panel_id, color_id, count(*) as cnt
    from votes
    group by panel_id, color_id
  )
  group by panel_id
) best_votes
join colors on colors.id = best_votes.maxcolor;