У меня есть таблица, которая содержит два поля. Первый - это name типа string. Вторая содержит одну или несколько строк, разделенных запятой (но может содержать одну строку без запятых)

Я хочу создать запрос, чтобы узнать, существует ли строка в поле name в каждой запятой строке в поле names.

Пример 1:

---------------------------------------------------------
name          names
---------------------------------------------------------
myname        xmyname,myname,mynamey

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

Но, Пример 2:

---------------------------------------------------------
name          names
---------------------------------------------------------
myname        x,myname,mynamey

Должен быть возвращен. Потому что х не содержит мое имя.

Условие состоит в том, что, если строка в поле name не существует в каждой разделенных запятыми строках в поле names, возвращайте строку.

Это не правильно, так как этот запрос не вернет true в примере 2 (который содержит x, который не содержит myname).

ВАЖНОЕ ПРИМЕЧАНИЕ:

1) Там не предел, сколько запятых там. Это может быть 0 запятых или больше. Как с этим бороться?

2) Строки являются переменными. Это не всегда тот случай, когда строка myname. Каждая строка содержит различную строку в поле name.

0
user9371654 1 Май 2019 в 15:32

4 ответа

Лучший ответ

Попробуйте это регулярное выражение:

where not concat(names, ',') regexp replace('^([^,]*{n}[^,]*,)*$', '{n}', name)

демо-версия db-fiddle

Как читать шаблон:

Внутренний шаблон [^,]*{n}[^,]*, означает

  • Любой символ без запятой [^,] повторяется любое количество раз (* означает ни раз, ни несколько раз).
  • сопровождается значением столбца name ({n} является заполнителем и будет заменен фактическим значением с помощью функции replace())
  • сопровождаемый любым не запятым символом [^,] повторяется любое количество раз
  • с запятой

Внешний шаблон ^({inner_pattern})*$ означает

  • Начало строки (^)
  • с последующим повторением внутреннего шаблона любое количество раз
  • с последующим концом строки ($)

Для этого к столбцу names (concat(names, ',')) добавляется запятая, поэтому каждый элемент в строке заканчивается запятой.

Шаблон будет гарантировать, что любой элемент в строке через запятую содержит значение столбца name. Поскольку вы хотите противоположный результат, мы используем where not ...

0
Paul Spiegel 1 Май 2019 в 13:35

Этот ответ начался с неправильного решения REGEXP. Но лучше всего было бы исправить вашу модель данных, чтобы каждое имя в столбце names находилось в отдельной строке:

name     | names
myname   | xmyname
myname   | myname
myname   | mynamey
somename | x
somename | myname
somename | mynamey

Теперь мы можем сделать простой запрос агрегации, чтобы ответить на ваш вопрос:

SELECT name
FROM yourTable
GROUP BY name
HAVING COUNT(CASE WHEN names NOT LIKE CONCAT('%', name, '%') THEN 1 END) > 0;

демонстрация

0
Tim Biegeleisen 1 Май 2019 в 13:05

Предполагая, что «мое имя» не появляется дважды между двумя запятыми, вы можете посчитать запятые и «мое имя»:

where (length(names) - length(replace(names, ','))) >=
       length(names) - length(replace(names, 'myname', '12345'))
0
Gordon Linoff 1 Май 2019 в 12:43

Вы можете подойти к этому, используя следующий SQL запрос

SELECT 
name, names
FROM 
`tablename` 
WHERE 
(LENGTH(names) - LENGTH(REPLACE(names, ',', '')) + 1) 
=  
ROUND (   
  (
        LENGTH(names)
        - LENGTH( REPLACE ( names, name, "") ) 
  )/ LENGTH(name)       
);

< Сильный > Объяснение : -

Это даст вам количество слов, разделенных ,

(LENGTH(names) - LENGTH(REPLACE(names, ',', '')) + 1) - 

Ниже приводится соответствие name в каждой строке и возвращается, сколько раз он нашел

 ROUND (   
    (
        LENGTH(names)
        - LENGTH( REPLACE ( names, name, "") ) 
    ) / LENGTH(name)        
)

DEMO

0
Rakesh Jakhar 1 Май 2019 в 14:27