加入mysql后如何按组/类别获取前n个解决方案?

时间:2019-03-25 11:11:53

标签: mysql join greatest-n-per-group row-number

我要联接2个表,然后希望每个组的前n个结果由第二个表中的一列排序。我的mysql版本不允许我使用row_number()和WITH子句。

通过此查询,我可以加入我的城市和夜生活表:

SELECT cities.id, cities.city, cities.country, cities.region, nightlife.rating
JOIN nightlife ON nightlife.cityID = cities.id
WHERE cities.popular = true 
ORDER BY nightlife.rating DESC;

通过此查询,我可以按最高ID依次为每个区域获取2个城市:

SELECT id, city, country, region
FROM cities
WHERE cities.popular = true
AND
(
   SELECT count(*) FROM cities AS c
   WHERE c.region = cities.region AND c.id >= cities.id
) <= 2;

如何在一个查询中将它们组合在一起,以获得每个地区的夜生活评分最高的前2个城市...而不使用row_number()和WITH子句?

预期结果

 id | city      | country | region | nightlife_rating
 ----------------------------------------------------
 1  | barcelona | spain   | europe | 10.0
 5  | paris     | france  | europe | 9.0
 23 | shanghai  | china   | asia   | 9.5
 54 | tokyo     | japan   | asia   | 9.3
 ...

示例架构..

CREATE TABLE cities (
    id int(11),
    city varchar(255),
    country varchar(255),
    region varchar(255),
    popular bool
);
INSERT INTO cities (id, city, country, region, popular)
VALUES  (1, 'barcelona', 'spain', 'europe', true),
        (3, 'rome', 'italy', 'europe', true),
        (5, 'paris', 'france', 'europe', true),
        (23, 'shanghai', 'spain', 'asia', true),
        (33, 'seoul', 'south-korea', 'asia', true),
        (54, 'tokyo', 'japan', 'asia', true);

CREATE TABLE nightlife (
    cityID int,
    rating float
);
INSERT INTO nightlife (cityID, rating)
VALUES  (1, 10.0),
        (3, 8.3),
        (5, 9.0),
        (23, 9.5),
        (33, 8.7),
        (54, 9.3);

与SQL Fiddle相同...

http://sqlfiddle.com/#!9/ccc4e4

3 个答案:

答案 0 :(得分:1)

SELECT n.id
     , n.city
     , n.country
     , n.region
     , n.popular
     , n.rating
  FROM 
     ( SELECT a.*
            , CASE WHEN @prev = region THEN @i:=@i+1 ELSE @i:=1 END i
            , @prev:=region prev 
         FROM
            ( SELECT c.*
                   , n.rating
                FROM cities c 
                JOIN nightlife n 
                  ON n.cityid = c.id 
               ORDER 
                  BY region
                   , rating DESC
            ) a
         JOIN ( SELECT @prev:=null,@i:=0) vars
      ) n
  WHERE n.i <= 2;

  +------+-----------+---------+--------+---------+--------+
  | id   | city      | country | region | popular | rating |
  +------+-----------+---------+--------+---------+--------+
  |   23 | shanghai  | spain   | asia   |       1 |    9.5 |
  |   54 | tokyo     | japan   | asia   |       1 |    9.3 |
  |    1 | barcelona | spain   | europe |       1 |     10 |
  |    5 | paris     | france  | europe |       1 |      9 |
  +------+-----------+---------+--------+---------+--------+

答案 1 :(得分:0)

您可以尝试使用UNION语句来获取该地区排名第一和第二的最佳城市。要获得第二高的值,我使用this这样的答案

SELECT  C.region, C.city, C.id, MAX(N.rating) as rating
FROM   cities C
INNER JOIN nightlife N
ON         C.ID = N.cityID 
GROUP BY C.region
UNION 
SELECT  C.region, C.city, C.id, MAX(N.rating) as rating
FROM   cities C
INNER JOIN nightlife N
ON         C.ID = N.cityID 
WHERE N.rating < (SELECT MAX(rating) 
                  FROM   nightlife 
                  INNER JOIN cities 
                  ON cities.ID = nightlife.cityID 
                  WHERE region = c.region)
GROUP BY C.region
ORDER BY region,rating desc,city

这是有效的解决方案fiddle

答案 2 :(得分:-1)

我理解您的问题是,您希望按降序排列具有城市详细信息的评分数据:

    select b.city,b.country,a.region,a.rating from
  (SELECT max(c.id) as city_id,
       c.region,
       max(n.rating) as rating from cities c
  JOIN nightlife n
ON n.cityID = c.id
WHERE c.popular = true
group by c.region
ORDER BY n.rating
DESC) a inner join cities b on a.city_id=b.id;