简体   繁体   English

MySQL:范围内的GROUP BY

[英]MySQL: GROUP BY within ranges

I have a table with scores like this: 我有一张分数如下的表格:

  score  |  user
 -------------------
     2   |  Mark
     4   |  Alex
     3   |  John
     2   |  Elliot
    10   |  Joe
     5   |  Dude

The table is gigantic in reality and the real scores goes from 1 to 25. 该表实际上是巨大的,真实分数从1到25。

I need this: 我需要这个:

  range   |  counts
 -------------------
   1-2    |  2
   3-4    |  2
   5-6    |  1
   7-8    |  0
   9-10   |  1

I've found some MySQL solutions but they seemed to be pretty complex some of them even suggested UNION but performance is very important. 我已经找到了一些MySQL解决方案,但是它们似乎非常复杂,其中一些甚至建议使用UNION但是性能非常重要。 As mentioned, the table is huge. 如前所述,桌子很大。

So I thought why don't you simply have a query like this: 所以我想为什么你不简单地拥有这样的查询:

SELECT COUNT(*) as counts FROM score_table GROUP BY score

I get this: 我得到这个:

  score  |  counts
 -------------------
    1    |   0
    2    |   2
    3    |   1
    4    |   1
    5    |   1
    6    |   0
    7    |   0
    8    |   0
    9    |   0
   10    |   1

And then with PHP, sum the count of scores of the specific ranges? 然后使用PHP,求和特定范围的分数计数? Is this even worse for performance or is there a simple solution that I am missing? 这会使性能更差吗?还是我缺少一个简单的解决方案?

Or you could probaly even make a JavaScript solution... 或者,您甚至可以提出一个JavaScript解决方案...

Your solution: 您的解决方案:

SELECT score, COUNT(*) as counts
FROM score_table
GROUP BY score
ORDER BY score;

However, this will not returns values of 0 for count. 但是,这不会返回计数值0 Assuming you have examples for all scores, then the full list of scores is not an issue. 假设您有所有分数的示例,那么分数的完整列表就不成问题了。 You just won't get counts of zero. 您只是不会得到零计数。

You can do what you want with something like: 您可以使用类似的方法做您想做的事情:

select (case when score between 1 and 2 then '1-2'
             when score between 3 and 4 then '3-4'
             . . .
        end) as scorerange, count(*) as count
from score_table
group by scorerange
order by min(score);

There is no reason to do additional processing in php. 没有理由在php中进行其他处理。 This type of query is quite typical for SQL. 这种查询对于SQL是非常典型的。

EDIT: 编辑:

According to the MySQL documentation , you can use a column alias in the group by . 根据MySQL文档 ,您可以在group by使用列别名。 Here is the exact quote: 这是确切的报价:

An alias can be used in a query select list to give a column a different name. 可以在查询选择列表中使用别名来为列指定其他名称。 You can use the alias in GROUP BY, ORDER BY, or HAVING clauses to refer to the column: 您可以在GROUP BY,ORDER BY或HAVING子句中使用别名来引用该列:

SELECT SUM(分数在1到2之间的情况然后...

Honestly, I can't tell you if this is faster than passing "SELECT COUNT(*) as counts FROM score_table GROUP BY score" into PHP and letting PHP handle it...but it add a level of flexibility to your setup. 老实说,我无法告诉您这是否比将“ SELECT COUNT(*)作为来自score_table GROUP BY分数的计数”传递到PHP中并让PHP处理它的速度更快...但是它为您的设置增加了一定程度的灵活性。 Create a three column table as 'group_ID', 'score','range'. 创建一个三列表作为“ group_ID”,“得分”,“范围”。 insert values into it to get your groupings right 在其中插入值以正确分组

1,1,1-2 1,1,1-2

1,2,1-2 1,2,1-2

1,3,3-4 1,3,3-4

1,4,3-4 1,4,3-4

etc... 等等...

Join to it on score, group by range. 加入得分,按范围分组。 THe addition of the 'group_ID' allows you to set groups...maybe have group 1 break it into groups of two, and let a group_ID = 2 be a 5 set range (or whatever you might want). 添加的“ group_ID”允许您设置组...也许让group 1将其分成两个组,并让group_ID = 2为5个设置范围(或您可能想要的任何值)。

I find the table use like this is decently fast, requires little code changing, and can readily be added to if you require additional groupings or if the groupings change (if you do the groupings in code, the entire case section needs to be redone to change the groupings slightly). 我发现这样的表使用非常快,几乎不需要更改代码,并且如果需要其他分组或分组发生更改,则可以很容易地添加到表中(如果您在代码中进行分组,则需要重做整个case部分)略微更改分组)。

If you want a simple solution which is very powerful, add an extra field within your table and put a value in it for the score so 1 and 2 have the value 1, 3 and 4 has 2. With that you can group by that value. 如果您想要一个简单且功能强大的解决方案,请在表格中添加一个额外的字段,并在其中添加一个值作为分数,以便1和2的值分别为1、3和4的值为2。 。 Only by inserting the score you've to add an extra field. 只有插入分数,您才需要添加一个额外的字段。 So your table looks like this: 因此您的表如下所示:

score  |  user     |   range
--------------------------
   2   |  Mark     |   1
   4   |  Alex     |   2
   3   |  John     |   2
   2   |  Elliot   |   1
  10   |  Joe      |   5
   5   |  Dude     |   3

Now you can do: 现在您可以执行以下操作:

select count(score),range from table group by range;

This is always faster if you've an application where selecting has prior. 如果您有一个选择优先的应用程序,这总是更快。

By inserting do this: 通过插入执行此操作:

$scoreRange = 2;
$range = ceil($score/$scoreRange);

How about this: 这个怎么样:

select concat((score + (1 * (score mod 2)))-1,'-',(score + (1 * (score mod 2)))) as score, count(*) from TBL1 group by (score + (1 * (score mod 2)))

You can see it working in this fiddle: http://sqlfiddle.com/#!2/215839/6 您可以看到它在此提琴中起作用: http ://sqlfiddle.com/#! 2/215839/6

For the input 对于输入

  score  |  user
 -------------------
     2   |  Mark
     4   |  Alex
     3   |  John
     2   |  Elliot
    10   |  Joe
     5   |  Dude

It generates this: 它生成此:

  range   |  counts
 -------------------
   1-2    |  2
   3-4    |  2
   5-6    |  1
   9-10   |  1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM