powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить сложный запрос
19 сообщений из 19, страница 1 из 1
Помогите составить сложный запрос
    #39828593
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет всем! Название темы умнее не придумал, т.к. в двух словах не опишешь :(

В общем, ситуация следующая. Есть простая таблица игроков, нас интересуют только поля "id" и "level".
Нужно получить N (например, 10) любых игроков, "id" которых должен быть в заданном списке, а уровень (level) находится в определённом диапазоне, причём уровень не должен повторяться.
Что-то вроде этого (константы для примера, у меня это переменные из PHP):

Код: sql
1.
SELECT id,level FROM `users` WHERE id IN (51,16,27,8,91,10,32,19,22,12,192,232,212) AND level BETWEEN 10 AND 20 GROUP BY level LIMIT 10



Здесь всё ОК, но вот потом, если запрос вернёт менее 10 игроков (например, нашёл 4), оставшиеся 6 надо "добить" игроками из базы по тем же условиям, но уже без проверки ID, типа того:

Код: sql
1.
SELECT id,level FROM `users` WHERE level BETWEEN 10 AND 20 GROUP BY level LIMIT 10



То есть те, перечисленные, игроки находятся как бы в приоритете :)

Попробовал сделать двумя запросами и в PHP их объединить в один массив, но тут мешают две проблемы - во-первых, второй запрос может выдать частично тех же людей, что и первый, но это не так страшно, есть варианты решения. А вот сделать, чтобы второй запрос не повторял значений level из первого - это уже сложнее :( Либо вместо BETWEEN делать перечисление "свободных" уровней, либо делать лимит в 2 раза больше (чем нужно) а потом в PHP отсеивать лишних...
Вопрос - нельзя ли вообще всё это как-нибудь организовать в одном сложном запросе? :) Заранее спасибо :)
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39828620
Фотография Щукина Анна
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Egis,

что делать в ситуации, если в таблице в принципе не набирается достаточного количества игроков с уникальными уровнями? К примеру, все игроки имеют одинаковый уровень. Или уровень ни одного из игроков не попадает в заданный диапазон уровней.
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39828778
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Щукина Анна,

Просто вернуть тех, которые нашлись (или ничего), в общем то что и делает запрос при указании LIMIT
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39837656
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Видимо, проще не получится, ну что ж...

А еще такой вопрос: допустим, мне надо получить по одному игроку каждого уровня, скажем от 1 до 20 (если на каком-то уровне ни одного игрока нет - ничего страшного) - каким образом ЭФФЕКТИВНЕЕ это сделать?

Простейший (и, возможно, наилучший) вариант, для примера:
Код: plsql
1.
SELECT id,level FROM `users` WHERE level BETWEEN 1 AND 20 GROUP BY level



Есть ли, например, смысл обозначать лимит в 20 человек, или GROUP и так прекращает поиск, если 20 человек найдено?

"Случайность" выборки не имеет значения, т.е. нужен любой первый попавшийся игрок с нужным уровнем.
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39837684
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уточните версию MySQL.
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39837862
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сервер: MySQL (Localhost via UNIX socket)
Версия сервера: 5.5.41-0+wheezy1
Версия протокола: 10
MySQL-кодировка: UTF-8 Unicode (utf8)
Apache/2.2.22 (Debian)
Версия MySQL-клиента: 5.5.41
PHP расширение: mysqli
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39837888
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну если в принципе всё равно какой id для каждого level вернётся, то максимальный (или там минимальный) подойдёт? Тогда я бы сделал так:

Код: sql
1.
2.
3.
4.
5.
6.
SELECT MAX(id) id, level 
FROM users 
WHERE level BETWEEN 10 AND 20 
GROUP BY level
ORDER BY id IN (51,16,27,8,91,10,32,19,22,12,192,232,212) DESC
LIMIT 10
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39837889
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, или коли уж версия 5.5 и чхать хотела на неполную группировку, MAX() убрать, и фиг с им, с несоответствием стандарту:

Код: sql
1.
2.
3.
4.
5.
6.
SELECT id, level 
FROM users 
WHERE level BETWEEN 10 AND 20 
GROUP BY level
ORDER BY id IN (51,16,27,8,91,10,32,19,22,12,192,232,212) DESC
LIMIT 10
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838118
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за ответ!

Я только не очень понял, что делает строчка
Код: sql
1.
 ORDER BY id IN (51,16,27,8,91,10,32,19,22,12,192,232,212) DESC



Если это ответ на первый вопрос (т.е. моя мечта искать в одном запросе сначала среди "приоритетных" ID, и если нужных уровней среди них нет то дополнить любыми с нужным уровнем), то у меня это не работает - всё равно возвращаются те же самые, не приоритетные случайные ID. Если указать MAX, то возвращаются другие, крупные (максимальные) id для тех же уровней, но указанные в списке никак не участвуют (разве что, попадаются случайно). Т.е. ORDER BY у меня вроде как ничего не меняет (только почему-то меняет порядок записей на хаотичный, но порядок записей не имеет для меня значения).
Пример без ORDER BY:
Код: sql
1.
2.
3.
4.
5.
SELECT id, level 
FROM users
WHERE level BETWEEN 1 AND 10 
GROUP BY level
LIMIT 10 (ничего не меняет, что логично, возможно влияет на быстродействие?)


Возвращает:
|1169123|1
|934302|2
|3484|3
|93331|4
|788599|5
|1630225|6
|996868|7
|405900|8
|260797|9
|568414|10

Пример с ORDER ID (перечислены реальные ID, их level точно входят в нужный диапазон):
Код: sql
1.
2.
3.
4.
5.
6.
SELECT id, level 
FROM users
WHERE level BETWEEN 1 AND 10 
GROUP BY level
ORDER BY id IN (18211095,31749108,2021239,3760319,3834192)
LIMIT 10


|3484|3
|93331|4
|260797|9
|405900|8
|568414|10
|788599|5
|934302|2
|996868|7
|1169123|1
|1630225|6
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838119
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не нашёл как редактировать сообщение... Когда пробовал последний раз забыл DESC, но это никак не повлияло на результат.
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838130
vkle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
EgisЯ только не очень понял, что делает строчка
Код: sql
1.
 ORDER BY id IN (51,16,27,8,91,10,32,19,22,12,192,232,212) DESC




Если это ответ на первый вопрос (т.е. моя мечта искать в одном запросе сначала среди "приоритетных" ID, и если нужных уровней среди них нет то дополнить любыми с нужным уровнем), то у меня это не работает

Попробуйте такой вариант:
Код: sql
1.
ORDER BY FIELD(id, 51,16,27,8,91,10,32,19,22,12,192,232,212) DESC




EgisНе нашёл как редактировать сообщение...И не найдете, нет такого функционала для пользователей.
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838132
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
[quot vkle]

Попробуйте такой вариант:
Код: sql
1.
ORDER BY FIELD(id, 51,16,27,8,91,10,32,19,22,12,192,232,212) DESC



Увы, точно такой же результат как для "ORDER BY id IN" :(
Всегда выбирает минимальный ID из ВСЕХ с подходящим уровнем.
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838134
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если пишу вот так:

Код: sql
1.
2.
3.
4.
5.
SELECT id, level, FIELD( id, 18211095, 31749108, 2021239, 3760319, 3834192 ) AS f
FROM users
WHERE level BETWEEN 1 AND 10 
GROUP BY level
ORDER BY f DESC 


то f всегда 0, и результат прежний.

Если убрать GROUP BY level, то первые 5 значений берутся из "приоритетных", и f = 5,4,3,2,1. Но, соответственно, вылезают все записи с повторяющимися уровнями :(
id - первичный уникальный ключ типа BIGINT, если что, мало ли...
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838144
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
EgisЯ только не очень понял, что делает строчка
Код: sql
1.
 ORDER BY id IN (51,16,27,8,91,10,32,19,22,12,192,232,212) DESC

Это, судя по первым двум словам, ORDER BY Clause. Т.е. предложение сортировки.
Сортировка выполняется по результату вычисления указанного выражения, причём по причине наличия DESC - в порядке убывания.
Оператор IN возвращает TRUE, если условие истинно (искомое значение присутствует в списке), иначе FALSE.
TRUE - это алиас целочисленного значения 1, FALSE - алиас целочисленного значения 0.
Т.е. фактически при сортировке сначала будут выведены записи со значением 1 (TRUE) - т.е. те, чьи id присутствуют в списке, а затем остальные (которых в списке нет).
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838297
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Akina,

Спасибо за разъяснения.
Всё работает как вы говорите, но, к сожалению для моего случая, уже только после процедуры группировки по уровню (как я понял) :(
С FIELD аналогично, если не делать группировку то всё было бы прекрасно...
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838350
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Egisдля моего случая, уже только после процедуры группировки по уровнюПрочитал три раза, ни разу не понял...
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838364
Egis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если написать GROUP BY level, то сначала, как я понимаю, происходит сама группировка по level (уровню), и только потом ORDER BY. Грубо говоря, сортировать после группировки уже нечего, возвращаются первые попавшиеся id с нужным level, ORDER BY уже не срабатывает, т.к. после группировки уже не остается "приоритетных" ID
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838452
vkle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Egis,

Подозреваю, что тупое решение "в лоб" тут будет и достаточно простым. Два запроса из первого поста соединить UNION и третим SELECT по результату объединения сделать итоговую десятку и сортировку.
Вроде бы, UNION сохраняет порядок записей из вложенных запросов, но если будет проблема с гарантированным получением в итоговом третьем запросе записей "обязательной" десятки, то, вероятно, в оба вложенных запроса придется добавить по одному полю с фиксированным значением, а в итоговом сделать по нему первый уровень сортировки.
...
Рейтинг: 0 / 0
Помогите составить сложный запрос
    #39838548
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
EgisГрубо говоря, сортировать после группировки уже нечего, возвращаются первые попавшиеся id с нужным level, ORDER BY уже не срабатывает, т.к. после группировки уже не остается "приоритетных" IDА что Вы хотите? изначально поставлена задача, гарантированно получающая недетерминированный результат. Именно он и получается - жаловаться не на что, сам попросил.
Меняй условия задачи.
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить сложный запрос
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]