У меня есть 1 соответствующая таблица для этого вопроса, награда:

----------------------------------------
| award                                |
----------------------------------------
| id | name | URL | country_id | point |
----------------------------------------
  1  | A    | a   | 1          | 120
  2  | A    | b   | 0          | 60
  3  | A    | b   | 2          | 80
  4  | B    | c   | 0          | 50
  5  | B    | d   | 1          | 70

Я хочу иметь возможность получить для списка заданных стран соответствующие разные награды (одна и та же награда имеет одно и то же имя) с наивысшим значением для столбца point.

Поэтому я попытался упорядочить свой запрос по пункту DESC и сгруппировать по имени, но это не помогло, я не получил ни нужного количества точек, ни правильного URL.

Я знаю, что могу сделать это легко, получив все данные из таблицы и сохранив только строку с наилучшим количеством точек, но должен быть способ сделать это только с SQL!

Запрос, который я попробовал, был:

SELECT name, URL, point FROM award WHERE country_id IN (0,1) ORDER BY point DESC GROUP BY name
1
hellimac 17 Апр 2016 в 06:42

2 ответа

Лучший ответ

Это должно дать вам то, что вы ищете:

SELECT t1.* FROM award AS t1
   INNER JOIN (SELECT name, MAX(point) AS point
      FROM award
      WHERE country_id IN (0,1)
      GROUP BY name) AS t2
   ON t1.name=t2.name
      AND t1.point=t2.point;

Вот как он ломается:

Это соединение таблицы award (обозначенной как t1) с подзапросом, обозначенным как t2. Подзапрос выглядит так:

SELECT name, MAX(point) AS point
    FROM award
    WHERE country_id IN (0,1)
    GROUP BY name

Подзапрос вернет максимальное количество баллов за каждое имя. Вот результаты подзапроса:

+------+-------+
| name | point |
+------+-------+
| A    |   120 |
| B    |    70 |
+------+-------+

Очевидно, это не включает URL. Если бы это было так, то URL должен был бы быть в GROUP BY, и тогда ваши записи были бы уникальной комбинацией name и URL (и тогда вы бы не получить максимальное значение балла).

Следующим шагом является присоединение к этой временной таблице, чтобы получить соответствующие строки в таблице award.

INNER JOIN (...) AS t2
    ON t1.name=t2.name
       AND t1.point=t2.point;

Объединение находит строки в таблице award, где name и point соответствуют name и point в результатах подзапроса. Это дает нам полные строки, которые мы хотим, и теперь мы можем получить доступ к URL. Результат выглядит так:

+------+------+------+------------+-------+
| id   | name | URL  | country_id | point |
+------+------+------+------------+-------+
|    1 | A    | a    |          1 |   120 |
|    5 | B    | d    |          1 |    70 |
+------+------+------+------------+-------+

Кроме того, на этом этапе вы можете выполнить заказ по столбцу в таблице award, который вам нужен, например по имени:

ORDER BY t1.name

Или наивысшее значение:

ORDER BY t1.point DESC
1
markwatsonatx 17 Апр 2016 в 05:50

Если вам нужен пункт desc, попробуйте

    SELECT name, country_id, point
FROM `award`
WHERE country_id IN (0,1)
GROUP BY name, country_id
ORDER BY name, point DESC

Результат

    name |country_id  |point
    =====|============|===========  
    A    |1           |120
    A    |0           |60
    B    |1           |70
    B    |0           |50
0
keronconk 17 Апр 2016 в 05:43