Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

Выбрать из таблицы MySQL по одинаковым значениям полей. Как лучше?

#mysql


Есть таблица учеников:

id | name | addr           | langs   | times | ages
 1 | Иван | Киев;Москва    | рус;укр | пн;пт |    4
 2 | Петр | Харьков;Москва | рус     | пт    |    4
 3 | Олег | Рига           | рус;лит | пн;вт |    5


.......

и т.д.

Из этих данных нужно собрать группу- т.е. выбрать из базы учеников с: 


Одним городом(пример: Москва - подходят Иван и Петр)
Одним языком(пример: рус - все подходят)
Одним днем недели(аналогично)
Одним возрастом.


Один момент: Если идет "подбор" по Москве, например, то подойдут те, у которых указан
город Москва+ могут "иметь" и другие города. Также и по другим полям
Как тут лучше поступить? А то пока в голову приходят только идиотские решения
    


Ответы

Ответ 1



Вам нужна команда FIND_IN_SET(). Если использовать Ваши критерии, то Одним городом(пример: Москва - подходят Иван и Петр) надо искать так: FIND_IN_SET('Москва', addr)>0 Одним языком(пример: рус - все подходят): FIND_IN_SET('рус', langs)>0 Проблема лишь в том, что FIND_IN_SET() использует запятую, как разделитель. Т.е. Вам придется еще REPLACE() добавить. Получается, что все москвичи + рус + пт будет так: SELECT * FROM table WHERE FIND_IN_SET('Москва', REPLACE(addr, ';', ','))>0 AND FIND_IN_SET('рус', REPLACE(langs, ';', ','))>0 AND FIND_IN_SET('пт', REPLACE(times, ';', ','))>0 Однако, @AlexceiShimakov прав: описанный Вами вид структуры базы не самый лучший. Запросы, особенно, если база большая, будут большие, сложные и длинные. Если у Вас есть возможность менять структуру - очень подумайте над этим. Ну а про необходимость индексов на всех поисковых полях я вообще молчу. :)

Ответ 2



Хранить города, где проживает студент через разделитель, плохая идея, лучше создать дочернюю таблицу "Города" и связать каждый город со студентом. Про остальные поля то же самое(там где данные с разделителем). После вынесения всех данных с разделителем в дочернюю таблицу, вы можете использовать обычный select c where, где вы можете отфильтровывать данные по городам, по возрастам. Если у вас нет возможности вынести данные в отдельную дочернюю таблицу, то для текущей таблицы я бы использовал функции https://stackoverflow.com/questions/14606900/mysql-create-a-simple-function, Функции можно использовать в операторе where, также как обычные условия, внутри функций парсил бы поле с разделителем, получал бы массив значений, искал среди массива переданный аргумент(например, какой-то конкретный город), и возвращал бы результат, найдено ли значение в поле.

Ответ 3



1.Если лень парсить и у вас ограниченный список городов/языков или что-то еще, воспользуйтесь функцией сравнения строк like, например: select * where concat(';',addr,';') like '%;Москва;% 2.На будущее - да, не храните так значения лучше, а выносите в отдельную таблицу, или парсите заранее. 3.Для понимания зачем и почему - советую ознакомиться с нормальными формами реляционных бд.

Комментариев нет:

Отправить комментарий