powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Переписать одним запросом
9 сообщений из 9, страница 1 из 1
Переписать одним запросом
    #39778658
Всем добрый день.

Досталась мне по наследству чудесная система. В ней используется Postgres 10.4. Есть в ней (примерно) такая таблица:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
create table prices
(
  price_date date not null,   -- дата определения цены
  price      numeric(18, 4),  -- цена на указанную дату
  sells      integer,         -- число продаж
  volume     numeric(18, 4),  -- объем проданного товара
  moneys     numeric(18, 4),  -- стоимость проданного товара
  constraint pk_prices
    primary key (price_date)
);



И есть в этой чудесной системе в одной из хранимых процедур несколько десятков подряд идущих идентичных запросов:
Код: sql
1.
2.
3.
4.
5.
6.
7.
UPDATE prices
SET price = prev.price, volume = 0, sells = 0, moneys = 0
FROM
  (SELECT * FROM prices) prev
WHERE prices.price_date = prev.price_date + INTERVAL '1 month'
  AND prices.volume = 0
  AND prices.price <> prev.price



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

Во-первых, непонятно, зачем там подзапрос. Я правильно понимаю, что если переписать по-простому, по-рабоче-крестьянски
Код: sql
1.
FROM prices prev


получим то же самое? Нет, ну я, конечно, проверил. Работает идентично. Но вдруг я чего-то не понимаю, вдруг у автора сего чуда были какие-то неведомые мне мотивы сделать так?

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

В связи с этим у меня вопрос: как бы переписать это (последовательность из десятков идентичных запросов) одним запросом?

Есть нюанс: за некоторые месяцы (их всего пара-тройка штук за все годы, но они есть) записи в таблице отсутствуют. Как я понимаю, эти месяцы становятся "непреодолимым барьером" - данные в своем неумолимом движении вперед не могут "перепрыгнуть" такую дырку. Это тоже необходимо учесть.

Есть идеи?
...
Рейтинг: 0 / 0
Переписать одним запросом
    #39778724
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"несколько десятков подряд идущих идентичных запросов"

идентичный - тождественный, полностью совпадающий.

Т.е. несколько десятков абсолютно одинаковых запросов?
...
Рейтинг: 0 / 0
Переписать одним запросом
    #39778729
Именно.

Несколько десятков подряд идущих абсолютно-абсолютно идентичных UPDATE-запросов.

А почему такое удивление? Непонятен смысл этого?
...
Рейтинг: 0 / 0
Переписать одним запросом
    #39778758
Друзья, всем спасибо, кто мысленно помогал мне. :)

При вашей мысленной поддержке у меня родился такой вариант:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
UPDATE prices p
SET volume = 0, sells = 0, moneys = 0, price =
  (SELECT price FROM prices p2
    WHERE EXTRACT (DAY FROM p.price_date) =  EXTRACT (DAY FROM p2.price_date)
    AND p.price_date > p2.price_date
    AND (p2.volume > 0
         OR NOT EXISTS (SELECT * FROM prices p3 WHERE p3.price_date = p2.price_date - INTERVAL '1 month'))
   ORDER BY p2.price_date DESC
   LIMIT 1
  )
WHERE p.volume = 0



Как я понял, "бесконечная" серия запросов в итоге приводит к тому, что для каждого месяца, в котором объемы продаж были нулевые, цена товара устанавливается равной цене товара в хронологически последнем из предшествующих месяцев, таких, что:
- в этом месяце были ненулевые объемы продаж ИЛИ
- для месяца, непосредственно предшествовавшего ему, в таблице нет записи.

Это же самое я попытался реализовать в одном отдельном запросе.

Ваше мнение?
...
Рейтинг: 0 / 0
Переписать одним запросом
    #39778823
Фотография полудух
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Антипов Андрей
Код: sql
1.
WHERE EXTRACT (DAY FROM p.price_date) =  EXTRACT (DAY FROM p2.price_date)


тут индекс не сработает
...
Рейтинг: 0 / 0
Переписать одним запросом
    #39778930
полудухтут индекс не сработает
Это не страшно - записей в таблице всего несколько тысяч.

Хуже другое. Я не смог прикрутить сюда "лишнее" условие исходного запроса, что заменяемое и заменяющее значения должны различаться.

Код: sql
1.
AND prices.price <> prev.price



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

Есть идеи, как допилить запрос?
...
Рейтинг: 0 / 0
Переписать одним запросом
    #39779222
Всем привет.

Ну собственно вот он, конечный вариант с проверкой условия неравенства заменяемого и заменяющего значения. Вложенный запрос пришлось повторить:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
UPDATE prices p
SET volume = 0, sells = 0, moneys = 0, price =
  (SELECT price FROM prices p2
    WHERE EXTRACT (DAY FROM p.price_date) =  EXTRACT (DAY FROM p2.price_date)
    AND p.price_date > p2.price_date
    AND (p2.volume > 0
         OR NOT EXISTS (SELECT * FROM prices p3 WHERE p3.price_date = p2.price_date - INTERVAL '1 month'))
   ORDER BY p2.price_date DESC
   LIMIT 1
  )
WHERE p.volume = 0 AND price <> 
  (SELECT price FROM prices p2
    WHERE EXTRACT (DAY FROM p.price_date) =  EXTRACT (DAY FROM p2.price_date)
    AND p.price_date > p2.price_date
    AND (p2.volume > 0
         OR NOT EXISTS (SELECT * FROM prices p3 WHERE p3.price_date = p2.price_date - INTERVAL '1 month'))
   ORDER BY p2.price_date DESC
   LIMIT 1
  )



Не очень эстетично, но вполне рабочий вариант. Есть идеи как сделать это компактнее?
...
Рейтинг: 0 / 0
Переписать одним запросом
    #39779546
grgdvo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Антипов Андрей,

Я точно вижу два одинаковых подзапроса?? Тогда хотя бы используйте WITH ( CTE)
...
Рейтинг: 0 / 0
Переписать одним запросом
    #39779547
grgdvo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
grgdvo,

А неее... Простите, не получится CTE, есть ссылка на исходную таблицу из UPDATE.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Переписать одним запросом
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]