Обновить несколько строк с определенными значениями и другие с нуля - PullRequest
0 голосов
/ 20 мая 2019

Как эффективно обновить несколько строк с определенными значениями для a_id 84, а затем для всех других строк установить 0 для того же a_id?

products

p_id    a_id     best 
 111      81       99
 222      81       99
 666      82       99
 222      83       99  
 111      84       99       
 222      84       99
 333      84       99
 111      85       99  
 222      85       99       

Прямо сейчас я делаю это:

SQL Fiddle

update products as u set
  best = u2.best
from (values
  (111, 84, 1),
  (222, 84, 2)
) as u2(p_id, a_id, best)
where u2.p_id = u.p_id AND u2.a_id = u.a_id
RETURNING u2.p_id, u2.a_id, u2.best

Но это только обновляет строки в values какожидается.Как мне также обновить строки не в values, чтобы они были 0 с a_id = 84?

Значение p_id из 333 должно иметь best = 0. Я мог бы явно включить каждыйp_id, но таблица огромна.

  • Значения, установленные в best, всегда будут иметь порядок от 1 до n , определяемый порядком values.
  • Таблица products содержит 1 миллион строк

Ответы [ 2 ]

1 голос
/ 20 мая 2019

Удалите условие u2.a_id = u.a_id из предложения ON и поместите его в присваивание с помощью оператора CASE:

update products as u set
  best = case when u2.a_id = u.a_id then u2.best else 0 end
from (values
  (111, 84, 1),
  (222, 84, 2)
) as u2(p_id, a_id, best)
where u2.p_id = u.p_id
1 голос
/ 20 мая 2019

Предполагая, что (p_id, a_id) является PK - или, по крайней мере, UNIQUE и NOT NULL, это один из способов:

UPDATE products AS u
SET    best = COALESCE(u2.best, 0)
FROM   products AS p
LEFT   JOIN ( VALUES
   (111, 84, 1),
   (222, 84, 2)
   ) AS u2(p_id, a_id, best) USING (p_id, a_id)
WHERE  u.a_id = 84
AND    u.a_id = p.p_id
AND    u.p_id = p.p_id 
RETURNING u2.p_id, u2.a_id, u2.best;

Сложность в том, что список FROM для UPDATE является эквивалентом INNER JOIN, тогда как вам нужен OUTER JOIN. Этот обходной путь добавляет таблицу products в список FROM (который обычно является избыточным), чтобы действовать в качестве левой таблицы для LEFT OUTER JOIN. Тогда работает INNER JOIN с products до products.

Чтобы дополнительно ограничить a_id = 84, добавьте еще одно предложение WHERE, сказав так. Это делает a_id = 84 избыточным в выражении VALUES, но оставляйте его там, чтобы избежать множественных объединений, которые будут отфильтрованы позже. Дешевле.

Если у вас нет PK или каких-либо других (комбинаций) UNIQUE NOT NULL столбцов, вы можете вернуться к системному столбцу ctid для объединения products строк. Пример:

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