В этом случае код, который вы выполняете для запуска sql, несколько сбивает с толку.Я переформулировал это ниже:
UPDATE player SET starter = 'TRUE' WHERE NOT EXISTS
(
SELECT school, weight, skill
FROM player b
WHERE b.school = player.school
AND b.weight = player.weight
AND b.skill > player.skill
)
Давайте сначала посмотрим на внутреннее выражение select.Это утверждение, по сути, запрашивает таблицу результатов с тремя столбцами (школа, вес, навык) из таблицы «игрок».Вы называете эту таблицу как 'b'.Вы тогда продолжаете фильтровать тремя вещами;является ли b.school эквивалентом player.school и так далее.
Ваша первая проблема заключается в том, что по вашему псевдониму b.school = player.school эквивалентно player.school = player.school.Для первых двух фильтров будут выбраны все строки - это ненужный расчет.Однако ваш последний фильтр всегда должен возвращать false, и поэтому ваш запрос, по всей вероятности, занимает так много времени: все строки будут возвращены из вашего внутреннего оператора select.
Предполагая, что во внешнем операторе выпсевдоним игрока, скажем, a, тогда вы получите отдельный результат, потому что теперь вы спрашиваете, находится ли игрок a в той же школе, имеет тот же вес и лучше.(1) Однако в данном случае вы сравниваете каждого игрока с любым другим игроком: для 170 000 игроков это 170 000 ^ 2 или примерно 39 миллиардов сравнений ... вот почему этот запрос такой медленный.
Есть два способа решения вашей проблемы.Во-первых, некоторые из этих программ должны обрабатываться программно.
- выберите все уникальные школы в качестве запроса
- для каждой школы, запустите аналогичный запрос
.Другое - сделать умное соединение SQL.Здесь я использую 'playerId' в качестве некоторого столбца, который является уникальным идентификатором.(Надеюсь, у вашей таблицы есть один.) (2)
SELECT a.playerId
FROM player a INNER JOIN player b
ON ( a.school = b.school AND a.weight = b.weight)
WHERE a.skill > b.skill
Используя встроенную функциональность соединения (3), этот запрос должен выполняться намного быстрее и привести к таблице всех возможных совпадений (только игроки в той же школе и в том же весе), который затем фильтруется по навыку.Исходная таблица результатов, предварительно отфильтрованная, будет намного меньше той, с которой вы работали.
И последнее.использование «не существует» довольно грязно и может повлиять на вашу производительность.Попробуйте что-то вроде:
UPDATE player c SET starter = 'TRUE' WHERE c.player IN
(
SELECT a.playerId
FROM player a INNER JOIN player b
ON ( a.school = b.school AND a.weight = b.weight)
WHERE a.skill > b.skill
)
(1) примечание: в некоторых реализациях sql возможно, что 'player' во внутреннем выражении будет интерпретироваться как 'player' во внешнем выражении, но я 'Я не уверен, что это гарантировано.Поэтому вы должны использовать псевдоним, чтобы быть уверенным.
(2) Я не на 100%, это будет работать, потому что у меня нет вашего стола для игры.
(3) SQL-серверыкак правило, построены, чтобы сделать это быстро.Но вы должны знать, как его использовать.