2012-03-04 3 views
9

У меня есть две таблицы (страна & уток), где в таблице стран есть каждая страна в мире, а таблица уток содержит список уток с полем country_id для ссылки на главную страну.MySQL возвращает первый ряд объединенного стола

Я пытаюсь получить список только стран с по крайней мере одной утиной в нем и с этой единственной соответствующей записью из таблицы уток для наивысшей оценки в этой стране. До сих пор у меня есть:

SELECT * 
FROM country c 
INNER JOIN ducks d ON c.id = d.country_id 
ORDER BY c.country ASC, d.rating DESC 

Это возвращает список каждой утки, а не только одну страну.

Буду благодарен, если кто-нибудь может указать мне в правильном направлении. Я бы предпочел сделать это в SQL, чем отдельный запрос для каждой страны, чтобы вытащить самую популярную утку.

+2

См: http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax- row-per-group-in-sql/для примеров того, как это сделать. – imm

+0

Какую утку вы хотите? кто-нибудь? – dotoree

+1

@dotoree Наивысший рейтинг (наивысший уток. Исходящий из набора) –

ответ

19
SELECT c.*, d.* 
FROM country c 
    INNER JOIN ducks d 
    ON d.id =       --- guessing the ducks Primary Key here 
     (SELECT dd.id     --- and here 
     FROM ducks dd 
     WHERE c.id = dd.country_id 
     ORDER BY dd.rating DESC 
     LIMIT 1 
     ) 

Индекс по (country_id, rating, id) для таблицы MyISAM или (country_id, rating) для таблицы InnoDB, w помощь.

Этот запрос покажет только один duck на страну, даже с более чем одним рейтингом. Если вы хотите, чтобы утки с привязанным рейтингом появлялись, используйте ответ @ imm's GROUP BY.

+0

Спасибо, что отлично работает –

+0

@ Имперский андер прекрасно. –

+0

+1 Очень приятно. Можно ли добиться этого без подзапроса? –

-1

Многие базы данных имеют некоторый эквивалент «select top 10 * from ...». В mySql синтаксис будет «select * from ... limit 10».

... НО ...

В этом случае uou действительно хотите "группу по" и "макс()"!

+1

Привет, группа ограничивает результаты, но функция MAX() просто отображает максимум для группы, но остальная часть строки содержит данные для первая запись, найденная MySQL, а не одна с максимальным рейтингом. Это то, что у меня есть до сих пор: 'SELECT c. *, D. *, MAX (d.rating) FROM country c INNER JOIN duck d ON c.id = d.country_id GROUP BY c.country ORDER BY c.country ASC, d.rating DESC' –

0

Попробуйте это:

SELECT c.country, MAX(d.rating) AS max_rating 
FROM country c 
JOIN ducks d ON c.id = d.country_id 
GROUP BY c.id 
ORDER BY c.country ASC 

Если "высокий рейтинг" является 1, а затем изменить MAX(d.rating) к MIN(d.rating)

+0

Привет, это очень близко, так как он возвращает одну страну с максимальным рейтингом, я также пытаюсь вернуть запись, соответствующую этому максимальному рейтингу. например, если я изменил первую строку вашего кода на 'SELECT c.country, d.id, d.rating, MAX (d.rating)', тогда d.rating не всегда равно MAX (d.rating), если это делает смысл –

+0

Да, это так. Я обновил ответ. Пожалуйста, попробуйте еще раз. –

+0

@ J.Bruni: 'HAVING' после' ORDER BY' недопустимый синтаксис. –

3

Вы можете попробовать:

SELECT c.*, d.* 
FROM country c 
INNER JOIN (
    SELECT d.country_id, d.id, MAX(d.rating) AS rating 
    FROM ducks d 
    GROUP BY d.country_id 
) q ON (q.country_id = c.id) 

INNER JOIN ducks d 
    ON (d.country_id, d.rating) = (q.country_id, q.rating) 
+0

Для этого нужно еще одно соединение, чтобы показать детали уток: 'INNER JOIN duck d ON (d.country_id, d.rating) = (q.country_id, q.rating)' –

+0

@ ypercube, true dat. – imm

8

Вы можете попробовать просто добавить присоединиться выбора, для

SELECT c.*, d.* 
FROM country c 
INNER JOIN ducks d ON c.id = d.country_id 
LEFT JOIN ducks d2 ON d.country_id = d2.country_id AND d2.rating > d.rating 
WHERE d2.id IS NULL 
+0

Отлично! Мне нравится эта версия. –

+1

И лучше иметь 'SELECT c. *, D. *'. Не нужно включать столбцы 'd2. *', Которые будут все NULL. –

+1

Это должно быть принятым ответом – ScottG

Смежные вопросы