Как выполнить поисковый запрос по значению столбца, содержащему строку со значениями, разделенными командой? - PullRequest
0 голосов
/ 09 октября 2018

У меня есть таблица, которая выглядит следующим образом

    date    |                            tags   |   name               
------------+-----------------------------------+--------         
 2018-10-08 | 100.21.100.1, cpu, del               ZONE1
 2018-10-08 | 100.21.100.1, mem, blr              ZONE2
 2018-10-08 | 110.22.100.3, cpu, blr               ZONE3
 2018-10-09 | 110.22.100.3, down, hyd              ZONE2
 2018-10-09 | 110.22.100.3, down, del              ZONE1

Я хочу выбрать name для тех строк, которые имеют определенные строки в столбце tags

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

Например, у меня есть список строк ["down", "110.22.100.3"].Теперь, если я посмотрю в таблицу, которая содержит строки в списке, я должен получить последние две строки с именами ZONE2, ZONE1 соответственно.

Теперь я знаю, что есть нечто, называемое inоператор, но я не совсем уверен, как использовать его здесь.

Я попробовал что-то вроде ниже

select name from zone_table where 'down, 110.22.100.3' in tags;

Но я получаю синтаксическую ошибку. Как мне это сделать?

Ответы [ 3 ]

0 голосов
/ 09 октября 2018

Вы можете сделать что-то вроде этого.

select name from zone_table where 
string_to_array(replace(tags,' ',''),',')@>
string_to_array(replace('down, 110.22.100.3',' ',''),',');

1) удалить пробелы в существующей строке для правильного разделения string_to_array без пробелов в начале, используя replace

2) string_to_arrayпреобразует вашу строку в массив, разделенный запятой.

3) @> - это оператор contains

(ИЛИ)

Если вы хотите сопоставить в целом

select name from zone_table where POSITION('down, 110.22.100.3' in tags)!=0

Для отдельных матчей вы можете сделать

select name from zone_table where POSITION('down' in tags)!=0 and 
POSITION('110.22.100.3' in tags)!=0

Подробнее о позиции здесь

0 голосов
/ 09 октября 2018

demo: db <> fiddle

Я бы сделал проверку с перекрытием массива (оператор &&):

SELECT name 
FROM zone_table 
WHERE string_to_array('down, 110.22.100.3', ',') && string_to_array(tags,',')
  1. Разделить вашсписки строк (значения столбцов и текст сравнения 'down, 110.22.100.3') в массивы с string_to_array() (конечно, если ваш сравниваемый текст уже является массивом, вам не нужно его разбивать)
  2. Теперь && оператор проверяет, перекрываются ли оба массива: проверяет, является ли один элемент массива частью обоих массивов ( документация ).


Примечание:
  1. «дата» - зарезервированное слово в Postgres.Я рекомендую переименовать этот столбец.
  2. В ваших примерах разделителем ваших строковых списков является ", ", а не ",".Вы должны позаботиться о пропусках.Либо ваш разделитель строк тоже равен ", ", либо вам следует объединить строки с помощью простого ",", что облегчает некоторые вещи (кроме полностью согласованных мыслей о сохранении значений в виде списков строк, составленных @TimBiegeleisen)
0 голосов
/ 09 октября 2018

Мы можем попробовать здесь использовать оператор LIKE и проверить наличие каждого тега в списке тегов CSV:

SELECT name
FROM zone_table
WHERE ', ' || tags LIKE '%, down,%' AND ', ' || tags LIKE '%, 110.22.100.3,%';

enter image description here

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

Важное примечание: Как правило, хранение данных CSV в таблицах SQL является плохой практикой по той самой причине, что она ненормализована и усложняет процесс.работать с.Было бы гораздо лучше, если бы каждый отдельный тег сохранялся в отдельной записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...