MySQL использует Filter Table на массиве других таблиц - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть две таблицы: профиль и хобби

Каждый профиль может выбрать до хобби, что будет сохранено в файле profile.p_hobbies как массив идентификаторов ( например: [1,5,7,8,9] )

Теперь я хочу получить имена хобби профиля.Я думаю, это должно быть что-то вроде ссылки:

SELECT hobbie.h_name
FROM profile, hobbie
WHERE profile.p_id=37 AND hobbie.h_id IN profile.p_hobbies

Результатом является ошибка # 1064

# 1064 - Фелер в синтаксисе SQL.Bitte die korrekte Синтаксис im Руководство пользователя nachschlagen bei 'profile.p_hobbies LIMIT 0, 25' в Zeile 3

Я уже использую метод IN в других SQL-запросах.Наверное, я не могу использовать его, если массив, который я хочу использовать, также является данными из базы данных SQL?

Могу ли я что-либо сделать без использования нескольких запросов?

Я используюMariaDB-9

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Ваш лучший выбор - нормализовать ваши данные.Хранение наборов чисел в виде списков, разделенных запятыми, считается вредным в SQL.Почему вредно?

  • он плохо масштабируется, потому что не может использовать индексы для поиска
  • обновить наборы чисел сложно;рассмотрим проблему удаления 2 из 1,2,3,4.В SQL это беспорядок.

Некоторые варианты SQL поддерживают функцию обновления.Но проблема масштабирования все еще существует.(Не обижайтесь на этот совет: большинство из нас в тот или иной момент допустили эту ошибку при проектировании базы данных.)

Между профилями и хобби у вас есть отношение многие ко многим.Поэтому вам нужна таблица с именем profile_hobbie с двумя столбцами, p_id и h_id.Когда профиль начинает заниматься хобби, вы вставляете строку в profile_hobbie с идентификатором профиля и хобби.Если профиль перестает заниматься хобби, вы удаляете эту строку.

Тогда ваш запрос будет выглядеть следующим образом:

  SELECT hobbie.h_name
    FROM profile
    JOIN profile_hobbie ON profile.p_id = profile_hobbie.p_id
    JOIN hobbie ON profile_hobbie.id = hobbie.h_id
   WHERE profile.p_id=37

Это даст (возможно, пустой) список хобби для выбранного профиля.

Вы также можете попробовать использовать Функция MySQL FIND_IN_SET () , но вы можете столкнуться с проблемами преобразования между целыми числами и строками.

   SELECT hobbie.h_name
     FROM profile
     JOIN hobbie ON (FIND_IN_SET(hobbie.h_id, profile.p_hobbies) > 0)

Но Гордон прав.Это использует паршивый хак для обработки строк.

0 голосов
/ 22 сентября 2018

Это слишком долго для комментария.

В MySQL нет такой вещи, как тип массива.У вас проблема с вашей структурой данных.У вас должна быть таблица ассоциация / junction , по одной строке на пользователя и хобби.Примерно так:

create table profileHobbies (
    profileHobbieId int auto_increment primary key,
    profileId int,
    hobbieId int,
    foreign key (profileId) references profiles(profileId),
    foreign key (hobbieId) references hobbies(hobbieId)
);

Строки будут выглядеть так:

profileHobbieId   profileId   HobbieId
       1              1           1
       2              1           3
       3              1           5

Тогда ваш запрос будет выглядеть так:

SELECT h.h_name
FROM profileHobbies ph JOIN
     hobbie h
     ON ph.hobbie_id = h.hobbie_id
WHERE ph.profile_id = 37 ;

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

  • Идентификаторы являются целыми числами.Данные должны храниться с использованием правильного типа, а целые числа не являются строками.
  • Должны быть правильно объявлены отношения с внешним ключом.
  • SQL имеет паршивые возможности обработки строк.
  • Строковые функциинеобходимый для управления списком не позволяет оптимизатору использовать индексы.
  • SQL имеет действительно отличную структуру данных для хранения списков.Она называется таблица , а не строка .
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...