Обновление с подсчетом и группировкой по выражениям - PullRequest
0 голосов
/ 05 марта 2020

Во-первых, я знаю, что в StackOverflow есть проблема с общиной, но следующие решения здесь не работают. Поэтому мне все еще нужна помощь.

Oracle - Обновление COUNT строк с указанным значением c

Oracle - Обновление строк с минимальное значение в группе столбца из другой таблицы

Oracle обновить оператор с групповой функцией

Oracle - Обновить COUNT из строки с указанным c значением

Проблема в : у меня таблица строк + 700k:

REVIEWS (PRODUCT_ID, REVIEW, REVIEW_DATE, RELEASE_DATE, ..., REVIEW_COUNT)

Я пытаюсь обновить REVIEW_COUNT считая строки с одинаковым PRODUCT_ID (я хочу просто отзывы перед выпуском продукта). Таким образом, де-код ниже работает очень хорошо для моей цели:

SELECT COUNT(PRODUCT_ID) FROM REVIEWS
WHERE REVIEW_DATE < RELEASE_DATE 
GROUP BY PRODUCT_ID 

Но мне трудно сделать обновление. Сначала я попробовал это:

UPDATE REVIEWS R
SET R.REVIEWS_COUNT = 
(SELECT COUNT(RR.PRODUCT_ID) FROM REVIEWS RR
WHERE RR.DATA < RR.REL_DATE
GROUP BY RR.PRODUCT_ID)

Ошибка "больше чем одна строка", что не удивительно, но так как я использую оператор group by, это не должно произойти. Поэтому я попробовал самостоятельное соединение:

UPDATE REVIEWS R
SET R.REVIEWS_COUNT = 
(SELECT COUNT(RR.PRODUCT_ID) FROM REVIEWS RR
WHERE RR.PRODUCT_ID = R.PRODUCT_ID AND RR.DATA < RR.REL_DATE)

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

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 05 марта 2020

Возможно, вместо обновления вы могли бы определить представление:

select product_id, review_date, release_date, 
       count(case when review_date < release_date then 1 end)
       over (partition by product_id) review_count
  from reviews;

Вы также можете попробовать merge вместо update:

merge into reviews a 
using (select product_id, count(product_id) cnt from reviews
        where review_date < release_date 
        group by product_id ) b
on (a.product_id = b.product_id)
when matched then update set reviews_count = b.cnt

dbfiddle

0 голосов
/ 05 марта 2020

Я думаю, что ваше второе обновление корректно:

UPDATE REVIEWS R
SET R.REVIEWS_COUNT = 
(SELECT COUNT(RR.PRODUCT_ID) FROM REVIEWS RR
WHERE RR.PRODUCT_ID = R.PRODUCT_ID AND RR.DATA < RR.REL_DATE)
;

Это обновит каждую запись в таблице отзывов. Это то, что вы хотели?

Индекс product_id ускорит выполнение внутреннего запроса, но все равно обновит все записи размером около 700 КБ.

...