У меня в базе данных 2 таблицы. Один для заказов, а другой для компаний.
Заказы имеют такую структуру:
OrderID | attachedCompanyIDs
------------------------------------
1 1,2,3
2 2,4
И у Компании такая структура:
CompanyID | name
--------------------------------------
1 Company 1
2 Another Company
3 StackOverflow
4 Nothing
Чтобы получить названия компаний заказа, я могу сделать запрос как таковой:
SELECT name FROM orders,company
WHERE orderID = 1 AND FIND_IN_SET(companyID, attachedCompanyIDs)
Этот запрос работает нормально, но следующий запрос - нет.
SELECT name FROM orders,company
WHERE orderID = 1 AND companyID IN (attachedCompanyIDs)
Почему работает первый запрос, а второй нет?
Первый запрос возвращает:
name
---------------
Company 1
Another Company
StackOverflow
Второй запрос возвращает только:
name
---------------
Company 1
Почему это так, почему первый запрос возвращает все компании, а второй запрос возвращает только первую?
Ответы:
attachedCompanyIDs
- скалярное значение, которое преобразуется вINT
(типcompanyID
).Приведение возвращает только числа до первой нецифровой (в вашем случае запятой).
Таким образом,
В
PostgreSQL
, вы можете преобразовать строку в массив (или сохранить ее в первую очередь как массив):и это даже будет использовать индекс на
companyID
.К сожалению, это не работает,
MySQL
поскольку последний не поддерживает массивы.Эта статья может вас заинтересовать (см.
#2
):Обновить:
Если есть разумное ограничение на количество значений в списках, разделенных запятыми (скажем, не более
5
), вы можете попробовать использовать этот запрос:источник
FIND_IN_SET
работает, но не использует индексы и может работать медленно при большом количестве информации в таблице компании.pos
элементы с началаCVS
и преобразует остальные в целое число.10 things in MySQL (that won’t work as expected)
CROSS JOIN
? Разве они не все одинаковы в MySQL?attachCompanyIDs - одна большая строка, поэтому mysql пытается найти компанию в этом преобразовании в целое число.
когда вы используете где в
поэтому, если comapnyid = 1:
это верно
но если цифра 1 не на первом месте
его возврат ложный
источник
Чтобы получить названия всех связанных компаний, а не на основе конкретного идентификатора.
источник
поскольку второй запрос ищет строки с идентификатором 1 ИЛИ 2 ИЛИ 3, первый запрос ищет одно из значений, разделенных запятыми, которые существуют в companyID,
и еще одна проблема здесь в том, что вы не присоединяетесь к таблицам с общим ключом в вашем where, поэтому вы получите мутацию строк, которая = count (table1) * count (table2);
Ваша проблема действительно существует с частью 2 моего ответа. (с вашим вторым запросом)
источник
Позвольте мне объяснить, когда использовать FIND_IN_SET и когда использовать IN.
Возьмем таблицу A, в которой есть столбцы с именами «помощь» и «аноним». Возьмем таблицу B, в которой есть столбцы с именами «bid», «bname», «aids».
Теперь в таблицах A и B есть фиктивные значения, как показано ниже.
Таблица А
помощь анаме
1 яблоко
2 банана
3 Манго
Таблица B
ставить bname помощники
1 яблоко 1,2
2 банана 2,1
3 Манго 3,1,2
Случай 1: если вы хотите получить эти записи из таблицы b, которая имеет 1 значение в столбцах вспомогательных средств, вам необходимо использовать FIND_IN_SET.
Запрос: выберите * из A JOIN B ON FIND_IN_SET (A.aid, b.aids), где A.aid = 1;
Случай 2: если вы хотите получить эти записи из таблицы a, которая имеет значение 1 ИЛИ 2 ИЛИ 3, присутствующее в вспомогательных столбцах, вы должны использовать IN.
Запрос: выберите * из A JOIN B ON A.aid IN (b.aids);
Теперь вот вам, что вам нужно с помощью запроса mysql.
источник
источник