Возвращает, какой элемент соответствует каждой строке в результате SQL

#sql #postgresql #case

Вопрос:

Я программно пишу SQL-запросы из пользовательского ввода. Я хочу показать пользователю для каждой возвращаемой строки, какая часть предоставленной им информации о запросе соответствует этой строке.

Например, предоставленная пользователем информация выглядит следующим образом:

 red:[11,202]
blue:[36]
green:[202]
yellow:[11,36]
 

Эта информация позволит построить следующий запрос:

 SELECT name, list FROM test WHERE list SIMILAR TO '%(11|202|36)%'
 

Но я хотел бы добавить поле результата, аналогичное «Сопоставленному элементу, показанному ниже:

Имя Список Согласованный Элемент
буфет 15,11,19,20 красный, желтый
привет 17,30,36,20 синий, желтый
бар 101,202,330,460 красный, зеленый
тест 15,36,23 Синий

Я не могу добавить примеры попыток, так как не знаю правильного языка, с помощью которого можно получить информацию. Мое текущее решение до сих пор заключается в обработке данных строка за строкой после того, как запрос вернет результат в мой скрипт для добавления нового столбца, но я хотел бы знать, возможно ли это сделать с помощью postgres.

Вот дб-скрипка: https://www.db-fiddle.com/f/nMMB3wVFRTGeZgobmA4F6k/1

Я использую postgresql 12.3, однако при необходимости могу изменить версию.

Комментарии:

1. Пожалуйста, опишите вводимые пользователем данные. Указывают ли разнесенные значения на 4 отдельных входа или на один вход с новым разделением строк. Является ли каждая из них отдельной строкой? Присутствуют ли скобки физически или являются индикаторами массива? … Возможно, размещение вашего решения по строкам было бы полезным. Это могло бы, по крайней мере, показать, как вы в настоящее время обрабатываете пользовательский ввод.

2. Пользовательский ввод-это несколько строк поиска, строки классифицируются, следовательно, красный, зеленый, синий, желтый. Исходное решение повторяет возвращенные строки и проверяет, встречаются ли в соответствующем столбце строки catogorized, если это так, то в строку добавляется новое свойство. Ответ ниже содержит отличные решения без необходимости в дополнительной информации, поэтому я не буду публиковать его, чтобы вопрос был кратким и значимым для других. Спасибо вам за ваш вклад!

Ответ №1:

Я согласен с Хэмбоном в том, что вам следует воспользоваться преимуществами массивов. Если вы не хотите создавать дополнительную таблицу, вы также можете сделать все это в одном запросе:

 select name, list,
  array_to_string(ARRAY[
      CASE WHEN list LIKE ANY(ARRAY['%', ' 2%']) then 'red' else null end,
      CASE WHEN list LIKE ANY(ARRAY['6%']) then 'blue' else null end,
      CASE WHEN list LIKE ANY(ARRAY[' 2']) then 'green' else null end,
      CASE WHEN list LIKE ANY(ARRAY['%', '6%']) then 'yellow' else null end
    ], ', ')
from test 
where list LIKE ANY(ARRAY['%', ' 2%', '6%', ' 2%', '%', '6%']);
 

Обратите внимание, что я использую КАК ЛЮБОЙ, а не ПОХОЖИЙ НА. Вы могли бы продолжать использовать АНАЛОГИЧНО, но мне кажется, что использовать его проще, ЧЕМ ЛЮБОЙ ДРУГОЙ.

Вот скрипка.

Комментарии:

1. Идеальное решение, получает то, что я хотел в запросе, без новой таблицы. Спасибо.

2. Очень креативно! Следует помнить об одном: если у вас есть значение «211», будет ли «%» фиксировать это в результирующем наборе?

Ответ №2:

Похоже, вам действительно нужно воспользоваться самой превосходной поддержкой массивов PostgreSQL. Мне кажется, что я часто это говорю.

Если вы измените свою структуру на массивы:

 create table test2 (
  name varchar(255),
  list integer[]
)
 

Затем, условно, вы даже можете поместить свои данные в другую таблицу:

 create table matches (
  color text,
  list integer[]
);

insert into matches values 
('red', '{11,202}'),
('blue', '{36}'), 
('green', '{202}'), 
('yellow', '{11,36}');
 

Следующий запрос должен дать результаты, которые вы ищете:

 select
  t.name, t.list, array_agg (m.color)
from
  test2 t
  join matches m on
    m.list amp;amp; t.list
group by
  t.name, t.list
 

Комментарии:

1. Это отличное решение, однако, поскольку оно требует вставки новой таблицы и данных и, предположительно, удаления при каждом поиске пользователя, накладные расходы меня немного отпугивают. Если бы данные запроса уже были в базе данных, то это было бы идеально. Спасибо.

2. Как бы то ни было, вы также можете рассмотреть временную таблицу… Я понимаю вашу озабоченность. Я скажу, что из-за дополнительных накладных расходов это очень масштабируемо, и если есть оболочка программы, она хорошо поддерживает переменные привязки по сравнению с поиском по подстановочным знакам.