Запрос возвращает значения перед вставкой данных - PullRequest
1 голос
/ 04 октября 2019

У меня есть таблица рейтинга.

CREATE TABLE merchants_rating(
    id          SERIAL PRIMARY KEY,
    user_id     INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
    merchant_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
    rating      INTEGER NOT NULL
);

Я хочу вставить в нее данные и получить сумму рейтинга продавца и числа пользователей, которые его оценили.

Я сделалзапрос.

WITH INSERT_ROW AS (
  INSERT INTO MERCHANTS_RATING (USER_ID, MERCHANT_ID, RATING) 
  VALUES(147, 92, 2)
)
SELECT SUM(R.RATING) AS SUMMA_RATING, COUNT(R.USER_ID) AS USER_COUNT 
FROM MERCHANTS_RATING AS R 
WHERE R.MERCHANT_ID = 92

Данные успешно добавлены, но в выходных данных есть проблемы. Когда таблица пуста и я впервые добавляю в нее данные, я получаю такие значения.

 SUMMA_RATING | USER_COUNT | 
----------------------------
     NULL     |     0      |

Хотя я ожидаю получить.

 SUMMA_RATING | USER_COUNT | 
----------------------------
      2      |      1      |

Поскольку один пользователь оценилпродавец.

Что я сделал не так?

Ответы [ 2 ]

4 голосов
/ 04 октября 2019

Цитата из руководства

Подвыражения в WITH выполняются одновременно друг с другом и с основным запросом. Следовательно, при использовании операторов изменения данных в WITH порядок, в котором фактически происходят указанные обновления, непредсказуем. Все операторы выполняются с одним и тем же снимком (см. Главу 13), поэтому они не могут «видеть» влияние друг друга на целевые таблицы

(выделено мной)

К счастью, в руководстве также объясняется, как обойти это:

Это [...] означает, что ВОЗВРАЩАЯ данные, это единственный способ сообщать об изменениях между различными подгруппами WITH-statements и основной запрос

Вам необходимо использовать UNION между существующими строками и вставленными строками:

WITH insert_row AS (
  INSERT INTO merchants_rating (user_id, merchant_id, rating) 
  VALUES (147, 92, 2)
  returning * --<< return the inserted row to the outer query
)
SELECT sum(r.rating) AS summa_rating, count(r.user_id) AS user_count 
FROM (
  SELECT rating, user_id
  FROM merchants_rating
  WHERE merchant_id = (SELECT merchant_id FROM insert_row)
  UNION ALL
  SELECT rating, user_id
  FROM insert_row
) r;

Если вы собираетесь вставить больше строки в первыйшаг, вам нужно изменить r.merchant_id = на r.merchant_id IN

Онлайн пример: https://rextester.com/BSCI15298

1 голос
/ 04 октября 2019

Я думаю, это то, что вы пытаетесь сделать.

  1. вставьте некоторые значения в merchants_rating из insert_row cte.
  2. выберите сумму и сосчитайте изтаблица merchants_rating
insert into merchants_rating (user_id, merchant_id, rating) 
with insert_row as ( 
  select 147, 92, 2 
) select * from insert_row;

select sum(rating) AS summa_rating, count(user_id) AS user_count 
from merchants_rating where merchant_id = 92;

См. SQLFIDDLE

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