2012-02-23 2 views
4

Я использую MySQL и у меня есть таблица членов с BLOB поле «Контакты», содержащий разделенные запятыми список идентификаторов другого пользователя:MySQL ВЫБРАТЬ IN следуют разделенные запятой поля

TABLE members: 
id_member = 1 
firstname = 'John' 
contacts (BLOB) = '4,6,7,2,5' 

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

SELECT firstname from members WHERE id_member IN (SELECT contacts FROM members WHERE id_member = 1); 

возвращает только одну строку, но когда я пытаюсь:

SELECT firstname from members WHERE id_member IN (4,6,7,2,5); 

Он возвращает все имена из списка. Я могу использовать два запроса для достижения этого, но я подумал, что я бы дважды проверял, есть ли способ заставить его работать с одним простым, элегантным запросом.

Спасибо за чтение, любая помощь оценена. июль

+0

Ваш ID цифровой и ваша блоб строка? – Jrod

+0

Решением здесь является правильная нормализация базы данных с таблицей контактов, имеющей два столбца: 'id_member' и' id_contact', для которых на 'id_member' много строк. –

+0

Да, Jrod, мой идентификатор INT, а blob - это строка. Спасибо за идею Майкл, но у меня есть запас для этого варианта, который я высказал в своем комментарии к ответу Тадмана. –

ответ

2

Можете вы изменить структуру БД? Поле контактов действительно должно быть связанной таблицей, а не столбцом. Предполагая таблицу контактов с этой структурой:

id_contact 
id_member 

Тогда вы будете использовать EXISTS вместо:

SELECT firstname from members m WHERE EXISTS (SELECT 1 FROM contacts c WHERE c.id_contact = m.id_member); 
+0

Это хороший запрос. Я собираюсь за сопутствующую таблицу, спасибо за вашу помощь –

5

Это похоже на очень плохой дизайн стола. Можно ли это изменить?

Если вы не можете изменить дизайн, то вы можете обращаться через запятую значения в MySQL с помощью FIND_IN_SET, но он не сможет эффективно использовать индексы:

SELECT firstname 
FROM members 
WHERE FIND_IN_SET(id_member, (SELECT contacts FROM members WHERE id_member = 1)) 

Но вместо того, чтобы идти по этому пути, Я бы сильно рекомендую, чтобы по возможности вы normalize your database. Рассмотрите возможность использования join table вместо списка, разделенного запятыми. Затем вы можете найти нужные вам записи с помощью объединений, и поиск сможет использовать индекс.

+0

Я не знал о 'FIND_IN_SET', но я уверен, что это будет жестоко медленным на больших наборах данных, поскольку это приводит к в автоматическом сканировании таблицы и не может быть проиндексирован. Впрочем, аккуратный трюк. – tadman

+0

Спасибо за исследовательские ссылки, очень полезно. Я собираюсь для нормализованного db –

3

Если вы используете сериализованный столбец типа BLOB, чтобы сохранить эти значения, вы не сможете делать то, что хотите. Другим подходом к SQL является создание таблицы отношений, которая может использоваться как часть операции JOIN, например таблицы member_contacts, которая имеет связь между одним значением id_member и некоторым другим.

Расширение списка, разделенного запятой, на отдельные записи - довольно простой механический процесс.

+0

Спасибо всем за ответы. Я рассматривал этот подход, но идея о том, что сбор списка контактов одного члена требует просмотра таблицы, заполненной контактами каждого пользователя, казалась неэффективной.Я обязательно поеду, если это будет быстрее. –

+0

Если вы указали это на 'id_member', который вы используете в своем предложении' WHERE', это на самом деле очень быстро даже на больших наборах данных. Всегда есть индексы для любых частых запросов. – tadman

+0

Спасибо, я закончил с этим –

Смежные вопросы