如何在加入 mysql 后得到 group/category 的前 n 个解决方案?

How to get top n solutions by group/category after join in mysql?

我要加入 2 table,然后希望每个组的前 n 个结果按第二个 table 的列排序。我的 mysql 版本不允许我使用 row_number() 和 WITH 子句。

通过这个查询,我可以加入我的城市和夜生活 tables:

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;

通过这个查询,我可以获得每个地区的 2 个城市,并按最高 ID 排序:

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

根据我的理解,你的问题是你想要包含城市详细信息的评级数据的 desc 顺序:

    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;

您可以尝试使用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

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 |
  +------+-----------+---------+--------+---------+--------+