简体   繁体   English

mysql限制分组

[英]mysql limit in group by

Say i have this table fields: 说我有此表字段:

Field1  Field2 Field3
a       1      1
a       1      2
a       1      3
a       1      4
a       2      1
a       2      2
a       2      3
a       3      1
b       1      1
b       1      2
b       1      3
b       2      1
c       1      1

and say i need to group by Field1 (because i need to some calucation on the data), is there a way to retrive only the first 2 elements grouped by Field2 (sorted desc)? 并说我需要按Field1分组(因为我需要对数据进行一些计算),有没有办法只检索按Field2分组的前2个元素(排序的desc)?

So for this example i'd like to retrive: 因此,对于此示例,我想检索:

a,3,1
a,2,3
a,2,2
a,1,4
a,1,3
b,1,2
b,1,1
b,2,1
c,1,1

would be something like 会像

SELECT field1, 
       Sum(field2), 
       Sum(field3) 
FROM   table t1 
WHERE  t1.Field1 IN (SELECT t2.Field1 
                     FROM   table t2 
                     WHERE  t2.Field1 = t1.Field1 
                     ORDER  BY Field2, 
                               Field3 DESC 
                     LIMIT  2) 
GROUP  BY field1 

A nice way to handle this if you are using MySQL 8+ or later is to use ROW_NUMBER : 如果您使用的是MySQL 8+或更高版本,则解决此问题的一种好方法是使用ROW_NUMBER

WITH cte AS (
    SELECT Field1, Field2, Field3,
        ROW_NUMBER() OVER (PARTITION BY Field1, Field2 ORDER BY Field3 DESC) rn
    FROM yourTable
)

SELECT Field1, Field2, Field3
FROM cte
WHERE rn <= 2
ORDER BY Field1, Field2 DESC, Field3;

在此处输入图片说明

Demo 演示版

If you are not using MySQL 8+, then this problem gets fairly hairy, fairly quickly. 如果您使用MySQL 8+,则此问题会变得相当冗长,很快。 The best way to do this in MySQL 5.7 or earlier would be to use session variables to simulate ROW_NUMBER . 在MySQL 5.7或更早版本中,执行此操作的最佳方法是使用会话变量模拟ROW_NUMBER But, this requires some verbose code. 但是,这需要一些冗长的代码。 You could also try to isolate the top two entries per group, but that two would take some verbose code. 您还可以尝试将每个组的前两个条目隔离开来,但其中两个条目将花费一些冗长的代码。 Really, if you have a long term need to run queries like this, then consider upgrading to MySQL 8+. 确实,如果您长期需要运行这样的查询,请考虑升级到MySQL 8+。

Pre MySQL 8.0 solution: MySQL 8.0之前的解决方案:

List only the last two values per (Field1, Field2) group: 每个(Field1, Field2)组仅列出最后两个值:

select *
from test t
where t.Field3 >= coalesce((
  select t1.Field3
  from test t1
  where t1.Field1 = t.Field1
    and t1.Field2 = t.Field2
  order by t1.Field3 desc
  limit 1
  offset 1
), 0)
order by Field1, Field2, Field3;

Result: 结果:

Field1  Field2  Field3
a       1       3
a       1       4
a       2       2
a       2       3
a       3       1
b       1       2
b       1       3
b       2       1
c       1       1

Get SUMs per Field1 group: 获取每个Field1组的SUM:

select t.Field1
     , sum(Field2)
     , sum(Field3)
from test t
where t.Field3 >= coalesce((
  select t1.Field3
  from test t1
  where t1.Field1 = t.Field1
    and t1.Field2 = t.Field2
  order by t1.Field3 desc
  limit 1
  offset 1
), 0)
group by t.Field1

Result: 结果:

Field1  sum(Field2)     sum(Field3)
a       9               13
b       4               6
c       1               1

Fiddle demo 小提琴演示

Note: this works fine, when the combination of (Filed1, Filed2, Filed3) is UNIQUE. 注意:当(Filed1, Filed2, Filed3)为UNIQUE时,此方法可以正常工作。 If Field3 can be duplicated within a (Field1, Field2) group, we would need more complex logic to limit the result to two rows per group. 如果可以在(Field1, Field2)组中复制Field3 ,则我们需要更复杂的逻辑以将结果限制为每组两行。

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

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