Проблема SQL, ЛЕВОЕ СОЕДИНЕНИЕ [..] В()
-
05-09-2019 - |
Вопрос
Эта небольшая ошибка SQL не дает мне покоя.Похоже, это не проблема с запросом, просто область видимости (?), примеры работают лучше всего:
SELECT ocp.*, oc.*, GROUP_CONCAT( u.username SEPARATOR ', ') AS `memjoined`
FROM gangs_ocs_process ocp, gangs_ocs oc
LEFT JOIN users u ON u.userid IN ( ocp.membersin )
WHERE ocp.ocid =1 AND ocp.gangid =1 AND oc.oc_name = ocp.crimename
GROUP BY ocp.ocid
LIMIT 0 , 30
Есть столбец (gangs_ocs_process.membersin), в котором есть список идентификаторов, которые присоединились (т. Е. 1,2,5).Я пытаюсь получить имена пользователей для каждого из этих идентификаторов (из users
таблицу) на одном дыхании.
Проблема в том, что LEFT JOIN users u ON u.userid IN ( ocp.membersin )
Если я заменю 1,2,4
в течение ocp.membersin
(ввод буквального списка вместо имени столбца), все работает нормально.Он возвращает столбец, содержащий имена пользователей (изображение).Однако, если я оставлю в ocp.membersin , я получу эту ошибку:
#1054 - Unknown column 'ocp.membersin' in 'on clause'
Это первый раз, когда я вообще использую IN в левых соединениях, так что я немного растерялся.
Любая помощь была бы замечательной :)
Решение
Я не думаю, что "IN" будет работать для этого синтаксиса.MySQL ожидает, что IN будет чем-то похожим на dataset, а не на строку с разделителями.Я думаю, вам нужно найти способ взять membersin, развернуть его в набор данных, с которым MySQL может работать (возможно, временную таблицу), и присоединиться к нему.
Другие советы
Если у вас в таблице есть строки с разделителями, значит, у вас проблема с дизайном в вашей базе данных.Добавьте новую таблицу для хранения этих значений.
Вы уверены, что 'membersin' находится в таблице 'gangs_ocs_process', а не в таблице 'gangs_ocs'?
Причина, по которой вы не можете заставить это работать, заключается в том, что сначала вам нужно привести вашу базу данных в НОРМУ.У вас НИКОГДА не должно быть списка идентификаторов в одном столбце.
Взглянув еще раз, я думаю, что ваша проблема заключается в попытке агрегирования в неправильной точке, а также в синтаксисе IN, и что вы должны агрегировать в подзапросе, ограниченном содержимым IN .Я недостаточно знаю о вашей схеме, чтобы сделать это "из коробки" правильным, но вы хотите что-то вроде этого.SomeKeyfield должно относиться обратно к gangs_ocs_process
SELECT ocp.*, oc.*, u.Memjoined
FROM gangs_ocs_process ocp, gangs_ocs oc
LEFT JOIN (Select SomeKeyField, GROUP_CONCAT( u.username SEPARATOR ', ') as memjoined
from users where userid in
(select membersin from gangs_ocs_process
where [whatever conditions] )
Group By SomeKeyField) u on ocp.SomeKeyField = u.SomeKeyField
WHERE ocp.ocid =1 AND ocp.gangid =1 AND oc.oc_name = ocp.crimename
GROUP BY ocp.ocid
LIMIT 0 , 30
Это такой плохой способ чтобы сохранить членство.
Но если вам все еще нужно жить с этим, вы можете попробовать REGEXP
соответствие для проверки на членство:
SELECT ocp.*, oc.*, GROUP_CONCAT( u.username SEPARATOR ', ') AS `memjoined`
FROM gangs_ocs_process ocp
LEFT JOIN users u ON (ocp.membersin RLIKE CONCAT('(^|,)[[:blank:]]?', userid, '[[:blank:]]?($|,)'))
JOIN gangs_ocs oc ON (ocp.ocid = 1 AND ocp.gangid = 1 AND oc.oc_name = ocp.crimename)
GROUP BY ocp.ocid
LIMIT 0 , 30