0

Выполнение условия WHERE IN по нескольким колонкам в PostgreSQL

1

У меня есть таблица '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 ответ(ов)

0

Вы можете использовать виртуальную таблицу для выполнения операции 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;

Таким образом, вы можете легко обновить записи в таблице, используя значения из виртуальной таблицы.

0

Да, должно работать. По крайней мере, у меня уже получалось сделать это в других SQL-запросах.

Вы пробовали? Вы можете протестировать это с помощью SET times_chosen = times_chosen.

0

Вы можете сделать это, если сначала приведете данные к массиву:

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;
Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь