Выполнение условия WHERE IN по нескольким колонкам в PostgreSQL
У меня есть таблица 'answers', в которой есть индексированный целочисленный столбец 'problem_id', целочисленный столбец 'times_chosen' и строковый столбец 'option'. В настоящее время единственными значениями столбца 'option' являются 'A', 'B', 'C' и 'D', хотя в будущем их может стать больше. Я хочу увеличить значение 'times_chosen' на 1 для множества (50-100) ответов, когда я знаю 'problem_id' и 'option' для каждого из них.
Мне нужен запрос, который что-то вроде этого:
UPDATE answers
SET times_chosen = times_chosen + 1
WHERE (problem_id, option) IN ((4509, 'B'), (622, 'C'), (1066, 'D'), (4059, 'A'), (4740, 'A')...)
Это возможно?
Правка: Оказалось, что это действительно возможно, используя именно тот синтаксис, который я придумал!
3 ответ(ов)
Вы можете использовать виртуальную таблицу для выполнения операции JOIN
следующим образом:
SELECT * FROM answers
JOIN (VALUES (4509, 'B'), (622, 'C'), (1066, 'D'), (4059, 'A'), (4740, 'A'))
AS t (p, o)
ON p = problem_id AND o = option
Аналогичный подход можно использовать и для выполнения операции UPDATE
. Пример может выглядеть так:
UPDATE answers
SET option = new_value
FROM (VALUES (4509, 'B'), (622, 'C'), (1066, 'D'), (4059, 'A'), (4740, 'A'))
AS t (p, o)
WHERE problem_id = t.p AND option = t.o;
Таким образом, вы можете легко обновить записи в таблице, используя значения из виртуальной таблицы.
Да, должно работать. По крайней мере, у меня уже получалось сделать это в других SQL-запросах.
Вы пробовали? Вы можете протестировать это с помощью SET times_chosen = times_chosen
.
Вы можете сделать это, если сначала приведете данные к массиву:
UPDATE answers
SET times_chosen = times_chosen + 1
WHERE ARRAY[problem_id::VARCHAR, option] IN ('{4509,B}', '{622,C}', ... )
Однако это будет невероятно неэффективно, поскольку не сможет использовать индексы. Использование JOIN, как предложил @Frank Farmer, является гораздо лучшим решением:
UPDATE answers a
SET times_chosen = times_chosen + 1
FROM (VALUES (4509,'B'), (622,'C'), ...) AS x (id, o)
WHERE x.id = a.problem_id AND x.o = a.option;
Выбрать первую строку в каждой группе GROUP BY?
Postgres: Как повысить пользователя до суперпользователя?
Как сбросить последовательность первичного ключа в Postgres, когда она потеряла синхронизацию?
Обновление строк таблицы в Postgres с использованием подзапроса
Как выполнить SELECT DISTINCT по нескольким столбцам?