简体   繁体   English

获取特定行组中的最大值

[英]Get the max value in a specific group of rows

I have these two tables: 我有这两个表:

popular_song 流行歌

song_name  | rate | country_id
------------------------------
Tic Tac    | 10   | 1
Titanic    | 2    | 1
Love Boat  | 8    | 2
Battery    | 9    | 2

country 国家

conutry_id | country
--------------------------
1          | United States
2          | Germany

What I'd like to achieve is to get the most poular song in each country, eg: 我想要实现的是获得每个国家/地区中最受欢迎的歌曲,例如:

song_name | rate | country
--------------------------
Tic Tac   | 10   | United States
Battery   | 9    | Germany

I've tried this query: 我试过这个查询:

SELECT MAX(rate), song_name, country
FROM popular_song ps JOIN country cnt
ON ps.country_id = cnt.country_id
GROUP BY country

But this doesn't work. 但这是行不通的。 I've tried looking at questions like "Order by before group by" but didn't find an answer. 我尝试查看“在分组之前先排序”之类的问题,但没有找到答案。

Which mysql query could achieve this result? 哪个mysql查询可以达到这个结果?

You can use another self join to popular songs table with the max rating 您可以将另一个自我加入到具有最高评分的流行歌曲表中

SELECT ps.*,cnt.country
FROM popular_song ps
JOIN (SELECT MAX(rate) rate, country_id FROM popular_song GROUP BY country_id) t1
ON(ps.country_id = t1.country_id and ps.rate= t1.rate)
 JOIN country cnt
ON ps.country_id = cnt.conutry_id

See Demo 观看演示

There is a trick that you can use with substring_index() and group_concat() : 您可以在substring_index()group_concat()使用一个技巧:

SELECT MAX(rate),
      substring_index(group_concat(song_name order by rate desc separator '|'), '|', 1) as song,
      country
FROM popular_song ps JOIN
     country cnt
     ON ps.country_id = cnt.country_id
GROUP BY country;

EDIT: 编辑:

If you have big tables and lots of songs per country, I would suggest the not exists approach: 如果您在每个国家/地区都设有大型餐桌和许多歌曲,那么我建议您使用not exists方法:

select rate, song country
from popular_song ps join
     country cnt
     on ps.country_id = cnt.country_id
where not exists (select 1
                  from popular_song ps2
                  where ps2.country_id = ps.country_id and ps2.rate > ps.rate
                 );

Along with an index on popular_song(country_id, rate) . 以及对popular_song(country_id, rate)的索引。 I recommended the group_concat() approach because the OP already had a query with a group by , so the trick is the easiest to plug into such a query. 我建议使用group_concat()方法,因为OP已经有一个带有group by的查询,因此技巧最容易插入到这样的查询中。

Here is another way I'v learned from @Gordon Linoff. 这是我从@Gordon Linoff中学到的另一种方法。 Here is that question you could learn too. 这也是您也可以学习的问题

SELECT  ps.*,cnt.country 
FROM 
  (SELECT popular_song.*,
         @rownum:= if (@c = country_id ,@rownum+1,if(@c := country_id, 1, 1) )as row_number
         FROM popular_song ,  
              (SELECT @c := '', @rownum:=0) r
         order by country_id, rate desc) as ps
LEFT JOIN country cnt
ON ps.country_id = cnt.conutry_id
WHERE ps.row_number = 1

This is the way of implementing row_number()(Partition by ...) window function in MySql. 这是在MySql中实现row_number()(Partition by ...)窗口函数的方法。

You can do this with EXISTS like this: 您可以使用EXISTS这样进行操作:

SELECT rate, song_name, cnt.country_id
FROM popular_song ps JOIN country cnt
ON ps.country_id = cnt.country_id
WHERE NOT EXISTS 
  (SELECT * FROM popular_song 
   WHERE ps.country_id = country_id AND rate > ps.rate)

It is not specified in the question whether two songs can be returned per country if their rating is the same. 问题中未指定如果两个国家的歌曲评级相同,是否可以在每个国家/地区返回两首歌曲。 Above query will return several records per country if ratings are not unique at country level. 如果国家/地区的分级不是唯一的,则上述查询将为每个国家/地区返回几条记录。

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

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