如何在加入 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一样...
根据我的理解,你的问题是你想要包含城市详细信息的评级数据的 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 |
+------+-----------+---------+--------+---------+--------+
我要加入 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一样...
根据我的理解,你的问题是你想要包含城市详细信息的评级数据的 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 |
+------+-----------+---------+--------+---------+--------+