Почему это условие mysql IN (1,2,3,4 ...) не работает, если в скобках много значений? - PullRequest
1 голос
/ 07 октября 2010

Я храню в столбце список состояний, разделенных запятыми:

Примерно так: 1,2,3,4,5,6,7,8 .. и так далее, простоих идентификаторы.

Затем я делаю запрос, чтобы получить все строки, которые имеют состояние с идентификатором 8, и это работает, когда список состояний имеет несколько элементов.

Этозапрос и таблица:

mysql> select id_partner, name, states from partner where 8 IN (states);
+------------+----------------+--------------------+
| id_partner | name           | states             |
+------------+----------------+--------------------+
|          1 | Inmo Inmo      | 8,9,10             |
|          2 | Foto Piso      | 8,9,10,11,12,13,14 |
|          4 | PARTNER 001-A  | 8                  |
|          6 | EnAlquiler     | 8                  |
|          7 | Habitaclia.com | 8,43,50            |
+------------+----------------+--------------------+
5 rows in set (0.00 sec)

Если в столбце состояний содержится 10 идентификаторов, разделенных запятой, он будет работать, но если он имеет 50 или более, он больше не будет работать.В приведенном выше результате он не покажет строку, которая имеет много состояний, включая строку с идентификатором 8.

Есть идеи?Я использую этот подход, чтобы не создавать другую таблицу для сохранения отношений между партнером и государствами, или мне лучше это сделать?

Ответы [ 2 ]

1 голос
/ 07 октября 2010

Ваша строка является одним значением, а не несколькими значениями. В нем содержатся запятые, но это все еще одна строка.

Значение строки в числовом контексте берется из первых цифр номера. Другими словами, числовое значение «123 456 789» равно 123. MySQL игнорирует все символы после первого нецифрового числа. (Это поведение в MySQL, другие базы данных могут вести себя по-разному).

Предикат IN( ) позволяет сравнивать с несколькими значениями, но вы должны сделать их отдельными выражениями SQL. Например, в следующих двух запросах только первый возвращает что-либо:

SELECT * FROM partner WHERE 5 IN ( 1, 2, 3, 4, 5 );

SELECT * FROM partner WHERE 5 IN ( '1,2,3,4,5' );

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

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

create table partner_states (
 id_partner int not null,
 id_state   int not null,
 primary key (id_partner, id_state)
);

Затем заполните его:

insert into partner_states (id_partner, id_state)
values (1, 8), (1, 9), (1, 10);

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

select id_partner, name, states 
from partner p join partner_states s on p.id_partner = s.id_partner
where s.id_state = 8

Запрос о партнерах, которые не соответствуют состоянию, которое вы можете сделать с внешним соединением:

select id_partner, name, states 
from partner p left outer join partner_states s on p.id_partner = s.id_partner
  and s.id_state = 8
where s.id_state is null
1 голос
/ 07 октября 2010

Это не то, как работает предложение IN - вам нужно использовать функцию FIND_IN_SET для поиска значений через запятую в одном столбце:

SELECT *  
  FROM partner 
 WHERE FIND_IN_SET(8, states) > 0

Реально, вы не должны хранить данные, разделенные запятыми. Он известен как денормализованные данные, и может быть сложно получить информацию о конкретных значениях в запятых.

...