Вы получили ваши (гарантированные) лекции по проектированию базы данных.
Что касается вашего вопроса, есть простой способ:
SELECT count(*) AS person_ct
FROM tbl t
WHERE translate((t)::text, '()', ',,')
~~ ('%,' || @desired_tool_id::text || ',%')
Или, если первый столбец - person_id
, и вы хотите исключить его из поиска:
SELECT count(*) AS person_ct
FROM tbl t
WHERE replace((t)::text, ')', ',')
~~ ('%,' || @desired_tool_id::text || ',%')
Объяснение
Каждая таблица сопровождается соответствующим составным типом в PostgreSQL. Таким образом, вы можете запросить любую таблицу следующим образом:
SELECT (tbl) FROM tbl;
Возвращает один столбец на строку, содержащий всю строку.
PostgreSQL может привести такой тип строки к тексту одним махом: (tbl)::text
Я заменяю оба символа ()
запятой ,
, поэтому каждые значение строки отделяется запятыми ,
.
Мой второй запрос не переводит открывающую скобку, поэтому первый столбец (person_id
) исключен из поиска.
Теперь я могу искать во всех столбцах с помощью простого выражения LIKE (~~
), используя желаемое число, разделенное запятыми ~~ %,17,%
Вуаля: все сделано одной простой командой. Это надежно, если в вашей таблице нет столбцов типа text
или int[]
, которые также могут содержать ,17,
в пределах своих значений, или дополнительных столбцов с числами, которые могут привести к ложным срабатываниям.
Он не даст чудес производительности, поскольку не может использовать стандартные индексы. (Вы могли бы создать индекс GiST или GIN для выражения, используя модуль tgrm в pg 9.1, но это уже другая история.)
В любом случае, если вы хотите оптимизировать, вам лучше начать с нормализации таблицы, как было предложено.