разница между where_in и find_in_set

Я работаю над запросом на соединение, в котором мне нужно получить данные из столбца, содержащего значения, разделенные запятыми. Например, allowed_activity содержит 1,2,3,4,5,6 это разрешенное activity_id.

Итак, в запросе я проверяю, разрешена ли текущая активность, и для этого я использовал where_in, а также пробовал find_in_set в состоянии where.

Вот эта часть запроса:

$this->db->where_in('a.allowed_activity',$activity_id);
//And With FIND_IN_SET
$this->db->where("FIND_IN_SET($activity_id, a.allowed_activity) !=",0);

Проблема или путаница

Когда я использую where_in, это не дает мне результата. Но если я использую FIND_IN_SET, он вернет желаемый результат. Я думал, что where_in может справиться с задачей, но это не так.

Просто хочу знать, почему find_in_set работает иначе, чем where_in Из-за того, что обе функции работают так же, как поиск данных в списке, разделенном запятыми.

Вот полный запрос:

SELECT mycolumns
FROM `table1` as `ea`
LEFT OUTER JOIN `table2` as `a` ON `ea`.`package_id` = `a`.`id`
LEFT OUTER JOIN `table3` as `e` ON `ea`.`employer_id` = `e`.`id`
WHERE `ea`.`card_id` > 0
AND FIND_IN_SET(6, a.allowed_activity) !=0
AND `ea`.`id` = '6'
ORDER BY `ea`.`creation_date` DESC

Я использую активную запись Codeigniter.


person ankit suthar    schedule 17.08.2017    source источник


Ответы (3)


WHERE IN требует, чтобы набор значений был указан в запросе буквально, а не как одно значение, содержащее строку с разделителями-запятыми. Если вы пишете:

WHERE 6 IN (a.allowed_activity)

он будет рассматривать a.allowed_activity как одно значение и сравнивать его с 6, а не как набор нескольких значений для поиска.

FIND_IN_SET ищет значение в строке с разделителями-запятыми.

Другой способ посмотреть на это состоит в том, что IN — это ярлык для набора тестов = в сочетании с OR:

WHERE x IN (a, b, c, d)

сокращение от

WHERE x = a OR x = b OR x = c OR x = d

Когда вы переписываете его таким образом, вы ясно видите, почему он не будет работать со столбцом, содержащим строку, разделенную запятыми. Это просто переводится

WHERE 6 IN (a.allowed_activity) 

to:

WHERE 6 = a.allowed_activity
person Barmar    schedule 17.08.2017

Следующий код неверен:

$this->db->where("FIND_IN_SET($activity_id, a.allowed_activity) !=",0);

Я удивлен, что это даже работает без ошибок, но одна из возможностей заключается в том, что он генерирует предложение WHERE, которое сравнивает строку с 0. Конечно, они никогда не будут равны, и поэтому это всегда будет верно.

Если вы хотите вызвать нативную функцию FIND_IN_SET(), вам нужно будет использовать whereRaw():

$this->db->whereRaw("FIND_IN_SET($activity_id, a.allowed_activity) !=0");

Использование WHERE IN (...) здесь некорректно, потому что у вас все значения в одной строке, разделенные запятыми. WHERE IN имело бы смысл, если бы вы хотели отфильтровать определенные значения из многих строк, каждый столбец имел бы одно значение.

person Tim Biegeleisen    schedule 17.08.2017
comment
whereRaw не имеет значения, сэр, он дает тот же результат, что и where @TimBiegeleisen - person ankit suthar; 17.08.2017
comment
Обновите свой вопрос полным запросом Laravel, который вы используете. Откуда этот псевдоним a, который вы используете? Я предполагаю, что ваш код является проблемой. - person Tim Biegeleisen; 17.08.2017
comment
Сэр, я использую CodeIgniter - person ankit suthar; 17.08.2017

FIND_IN_SET искать значение в массиве и возвращать индекс значения, тогда, если функция отличается от 0, это означает, что значение присутствует в списке. так что код

  this->db->where("FIND_IN_SET(6, a.allowed_activity) !=",0);

означает возврат индекса значения 6 в a.allowed_activity
, и если возвращаемое значение отличается от 0, то значение 6 присутствует в a.allowed_activity

WHERE ... IN проверить, есть ли значение в наборе, но не возвращать индекс .. просто вернуть true или false, если значение присутствует или нет

person scaisEdge    schedule 17.08.2017