Ето пет опции за използване на SQL за връщане само на онези редове, които имат максимална стойност в тяхната група.
Тези примери работят в повечето основни RDBMS, включително MySQL, MariaDB, Oracle, PostgreSQL, SQLite и SQL Server.
Примерни данни
Да предположим, че имаме таблица със следните данни:
ИЗБЕРЕТЕ * ОТ Gameshow;
Резултат:
<пред>+--------------+-------+-------+| Състезател | Игра | Резултат ||--------------+-------+--------|| Фей | 1 | 85 || Фей | 2 | 50 || Фей | 3 | 63 || Реактивен | 1 | 31 || Реактивен | 2 | 40 || Реактивен | 3 | 51 || Спайк | 1 | 25 || Спайк | 2 | 27 || Спайк | 3 | 15 |+--------------+-------+-------+И да предположим, че искаме да получим най-висок резултат за всеки състезател.
Опция 1
Бърза и лесна опция е да създадете заявка с SQL GROUP BY
клауза:
ИЗБЕРЕТЕ състезател, МАКС (резултат) КАТО MaxScoreFROM GameshowGROUP BY ContestantORDER BY Contestant;
Резултат:
+--------------+-----------+| Състезател | MaxScore ||--------------+-----------|| Фей | 85 || Реактивен | 51 || Спайк | 27 |+--------------+-----------+
Опция 2
Ако искаме да включим играта, която всеки състезател играе, за да получим максималния резултат, тогава един от начините да направим това е да използваме корелирана подзаявка като тази:
ИЗБЕРЕТЕ състезател, игра, резултат ОТ Gameshow g1WHERE Резултат =( SELECT MAX( g2.Score ) ОТ Gameshow g2 WHERE g1.Contestant =g2.Contestant )ПОРЪЧКА ПО Състезател;
Резултат:
<пред>+--------------+-------+-------+| Състезател | Игра | Резултат ||--------------+-------+--------|| Фей | 1 | 85 || Реактивен | 3 | 51 || Спайк | 2 | 27 |+--------------+-------+--------+Корелираните подзаявки се отнасят до една или повече колони извън подзаявката. Корелираните подзаявки могат да бъдат неефективни, главно поради факта, че подзаявката се изпълнява многократно, веднъж за всеки ред, който може да бъде избран от външната заявка. Корелираните подзаявки са известни също като повтарящи се подзаявки.
Опция 3
Като алтернатива можем да използваме некорелирана подзаявка като тази:
ИЗБЕРЕТЕ g1.Contestant, g1.Game, g1.ScoreFROM Gameshow g1JOIN ( SELECT Contestant, MAX( Score) КАТО Резултат ОТ Gameshow ГРУПА ПО Състезател) AS g2 ON g1.Contestant =g2.Contestant И g1.Score =g2.ScoreORDER BY Contestant ASC;
Резултат:
<пред>+--------------+-------+-------+| Състезател | Игра | Резултат ||--------------+-------+--------|| Фей | 1 | 85 || Реактивен | 3 | 51 || Спайк | 2 | 27 |+--------------+-------+--------+Некорелираните подзаявки не зависят от външната заявка за тяхното изпълнение. Те могат да се изпълняват напълно независимо от външната заявка.
В Oracle трябва да премахнем AS
при деклариране на псевдоними на колоните:
ИЗБЕРЕТЕ g1.Contestant, g1.Game, g1.ScoreFROM Gameshow g1JOIN ( SELECT Contestant, MAX( Score) Резултат ОТ Gameshow ГРУПА ПО Състезател) g2 ON g1.Contestant =g2.Contestant И g1.Score =g2 .ScoreORDER BY Contestant ASC;
Опция 4
Друга възможност е да използвате LEFT JOIN
, като това:
ИЗБЕРЕТЕ g1.Contestant, g1.Game, g1.ScoreFROM Gameshow g1LEFT JOIN Gameshow g2 ON g1.Contestant =g2.Contestant AND g1.Score
Резултат:
<пред>+--------------+-------+-------+| Състезател | Игра | Резултат ||--------------+-------+--------|| Фей | 1 | 85 || Реактивен | 3 | 51 || Спайк | 2 | 27 |+--------------+-------+--------+Опция 5
Друг начин за извличане на редове с максимална стойност в дадена колона е да използвате общ табличен израз с функция прозорец:
С cte AS ( ИЗБЕРЕТЕ състезател, игра, резултат, RANK() НАД ( РАЗДЕЛЯНЕ ПО състезател ПОРЪЧКА ПО РЕЖИМ НА Резултат ) КАТО r ОТ Gameshow )ИЗБЕРЕТЕ Състезател, игра, РезултатFROM cteWHERE r =1 ПОРЪЧКА ПО Състезател ASC;код>
Резултат:
<пред>+--------------+-------+-------+| Състезател | Игра | Резултат ||--------------+-------+--------|| Фей | 1 | 85 || Реактивен | 3 | 51 || Спайк | 2 | 27 |+--------------+-------+--------+