#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. Как бы то ни было, вы также можете рассмотреть временную таблицу… Я понимаю вашу озабоченность. Я скажу, что из-за дополнительных накладных расходов это очень масштабируемо, и если есть оболочка программы, она хорошо поддерживает переменные привязки по сравнению с поиском по подстановочным знакам.