ВЫБРАТЬ ИЗ таблицы, ГДЕ точное число не является частичным в строке SQL - PullRequest
0 голосов
/ 22 января 2019

У меня есть таблица, содержащая набор чисел, разделенных запятой.

Я хотел бы получить строки из таблицы, где точное число, а не частичное число находится внутри строки.

Пример:

CREATE TABLE IF NOT EXISTS `teams` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `uids` text NOT NULL,
  `islive` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

INSERT INTO `teams` (`id`, `name`, `uids`, `islive`) VALUES
(1, 'Test Team', '1,2,8', 1),
(3, 'Test Team 2', '14,18,19', 1),
(4, 'Another Team', '1,8,20,23', 1);

Я бы хотел найти где 1 в строке.

В настоящее время, если я использую Contains или LIKE, он возвращает все строки с 1, но 18, 19 и т. Д. Не равен 1, но содержит 1.

Я настроил здесь sqlfiddle

Мне нужно сделать регулярное выражение?

Ответы [ 5 ]

0 голосов
/ 23 января 2019

Ваш SQL Fiddle использует MySQL, и ваш синтаксис соответствует MySQL. Существует встроенная функция для использования:

select t.*
from teams t
where find_in_set(1, uids) > 0;

Сказав это, ИСПРАВИТЕ СВОЮ МОДЕЛЬ ДАННЫХ, ЧТО ВЫ НЕ ХРАНИТЕ СПИСКИ В ОДИНОЧНОЙ КОЛОННЕ. Извините, что вышло так громко, это всего лишь важный принцип проектирования базы данных.

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

  • Числа должны храниться как числа, а не строки.
  • Столбцы должны содержать одно значение.
  • Должны быть должным образом объявлены отношения внешнего ключа.
  • SQL (в общем) имеет паршивые функции обработки строк.
  • Полученные запросы не могут быть оптимизированы.
  • Простые вещи, такие как перечисление uid в порядке или удаление дубликатов, излишне трудны.
0 голосов
/ 22 января 2019

Вы не указали, какую версию SQL Server вы используете, но если вы используете 2016+, у вас есть доступ к функции STRING_SPLIT , которую вы можете использовать в этом случае. Вот пример:

CREATE TABLE #T
     (
        id int,
        string varchar(20)
     )

     INSERT INTO #T
     SELECT 1, '1,2,8' UNION
     SELECT 2, '14,18,19' UNION
     SELECT 3, '1,8,20,23' 


     SELECT * FROM #T
     CROSS APPLY string_split(string, ',')
     WHERE value = 1
0 голосов
/ 22 января 2019

Я бы искал все четыре возможных местоположения идентификатора, который вы ищете:

  • В качестве единственного элемента списка.
  • В качестве первого элемента списка.
  • как последний элемент списка.
  • как внутренний элемент списка.

Запрос будет выглядеть следующим образом:

select *
from teams
where uids = '1' -- only
   or uids like '1,%' -- first
   or uids like '%,1' -- last
   or uids like '%,1,%' -- inner
0 голосов
/ 22 января 2019

Вам нужно только 1 условие:

select *
from teams
where concat(',', uids, ',') like '%,1,%'
0 голосов
/ 22 января 2019

Вы, вероятно, могли бы поймать их всех с помощью ИЛИ

SELECT ...

WHERE uids LIKE '1,%'
OR  uids LIKE '%,1'
OR uids LIKE '%, 1'
OR uids LIKE '%,1,%'
OR uids = '1'
...