Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> PostgreSQL: суммировать от 12:00 до 11:59(сл. дня), хитрая группировка по датам продажи 
:(
    Опции темы
sneer
Дата 28.1.2009, 23:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 13.10.2008

Репутация: нет
Всего: нет



есть простенькая структура бд.
Продаём товар. Основная таблица sold в которую вноситься ай-ди товара, дата_айди, кол-во проданного и время продажи
есть такие тейблы
date -(id,date)
goods -(id,name,price_id)
price - (id,opg,retail) // айди,оптовая и розничная цена
sold - (id, goods_id, date_id,quantity, time ) //ай-ди, ай-ди товара, ай-ди даты, кол-во проданного и время

есть ещё таблицы например склад из которого по тригеру отнимается занесённое в sold но эт здесь не важно. 
Суть такова. Нужна такая таблица. Число. Сумма всего проданного в деньгах. Я сделал это так для одного дня.

Код

SELECT sum( money.retail) as sum FROM (SELECT price.retail from trim.price RIGHT JOIN (SELECT goods.price_id
   FROM "trim".goods
   RIGHT JOIN "trim".sold ON sold.goods_id = goods.id
  WHERE sold.date_id = 302 AND sold."time" > '22:00:00'::time without time zone 
AND sold."time" < '23:59:59'::time without time zone OR sold.date_id = 308 AND sold."time" < '04:00:00'::time without time zone) 
AS today_price ON today_price.price_id=price.id) AS money;

Мне нужно сделать так что бы даты отсюда
Код

select DISTINCT ON (date_id) date from trim.sold LEFT JOIN trim.date ON (date_id=date.id) WHERE time>'22:00' AND time<'23:59:59';

были в одной таблице с суммами по этой дате.
По поводу тацев с временем и датами. Торговля идёт ночью )) до двенадцати и после двенадцати. А торговый день условно один.
Как решение. Можно сделать функцией. Можно ли это сделать исключительно sql без отдельной функции?
БД Postgresql 8.3

Это сообщение отредактировал(а) sneer - 29.1.2009, 00:00
PM MAIL   Вверх
sneer
Дата 29.1.2009, 02:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 13.10.2008

Репутация: нет
Всего: нет



мне тут немножко поправили заголовок время там чуток не правильно а так суть верна. найти сумму по каждой дате из второго запроса. Сумма находится первым запросом.Фокусы с датой можно пока убрать вообще. 
updt похоже суть вопроса правильно применить IN и JOIN вот только как...

Это сообщение отредактировал(а) sneer - 29.1.2009, 05:05
PM MAIL   Вверх
skyboy
Дата 29.1.2009, 10:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 15
Всего: 260



Цитата(sneer @  28.1.2009,  22:30 Найти цитируемый пост)
Мне нужно сделать так что бы даты отсюда
<... code here ...>
были в одной таблице с суммами по этой дате.

т.е. чтоб и запись "дата + сумма за дату" и запись "дата + количество + товар + время" были в одной таблице-результате? Вообще для такого используется не join(т.е. запись с суммой будет одна, а вот записей с соответствующими дате продажами может быть неопределенное и неограниченное количество), а union.
но я бы хотел с тобой поспорить насчет необходимости столь разнородные по структуре(количеству полей) и по значению пихать в один запрос. Если тебе необходимо сформировать отчет(для печати или подобного чего-то), может суммировать не средствами СУБД, а на клиенте уже?
 
PM MAIL   Вверх
sneer
Дата 29.1.2009, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 13.10.2008

Репутация: нет
Всего: нет



я об этом думал но отчёт именно в такой форме да и просто интересно как склеит в кучу эти два запроса. Ща по union почитаю ещё раз доки. Как то слабо вижу решение в его использовании. Мне почему-то кажеться что sql будет быстрее нежели либой язык который будет получать запрос обрабатывать а потом по одному опять тыкать запрос. Скорость там не критична но всегда нужно стараться сделать лучше.
  Тут впринципе как правильно скармливать даты по очереди самому нижнему join который уже есть ведь запрос рабочий осталось только сделать так что бы дат было несколько и он выводил их по очереди.

Это сообщение отредактировал(а) sneer - 29.1.2009, 20:50
PM MAIL   Вверх
sneer
Дата 30.1.2009, 01:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 13.10.2008

Репутация: нет
Всего: нет



Упростил всё что бы нагляднее.
три таблицы date price sold sold имет ключи на две остальных. расматриваемый пример кол-во продаваемого всегда 1 для простоты. Вот дамп.

Код

CREATE TABLE testing.date
(
  id bigint NOT NULL,
  date bigint NOT NULL,
  CONSTRAINT pkey PRIMARY KEY (id)
)
WITH (OIDS=FALSE);



Код


CREATE TABLE testing.price
(
  id bigint NOT NULL,
  price bigint NOT NULL,
  CONSTRAINT price_pkey PRIMARY KEY (id)
)



Код

CREATE TABLE testing.sold
(
  id bigint NOT NULL,
  date bigint NOT NULL,
  quantity bigint NOT NULL,
  price bigint NOT NULL,
  CONSTRAINT sold_pkey PRIMARY KEY (id),
  CONSTRAINT sold_date_fkey FOREIGN KEY (date)
      REFERENCES testing.date (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT sold_price_fkey FOREIGN KEY (price)
      REFERENCES testing.price (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)



Код


COPY date (id, date) FROM stdin;
1    5
2    10
3    15
\.




Код

INSERT INTO price (id, price) VALUES (1, 11);
INSERT INTO price (id, price) VALUES (2, 22);
INSERT INTO price (id, price) VALUES (3, 44);
INSERT INTO price (id, price) VALUES (4, 55);



Код

INSERT INTO sold (id, date, quantity, price) VALUES (1, 1, 1, 1);
INSERT INTO sold (id, date, quantity, price) VALUES (2, 1, 1, 2);
INSERT INTO sold (id, date, quantity, price) VALUES (3, 1, 1, 3);
INSERT INTO sold (id, date, quantity, price) VALUES (4, 1, 1, 1);
INSERT INTO sold (id, date, quantity, price) VALUES (5, 2, 1, 2);
INSERT INTO sold (id, date, quantity, price) VALUES (6, 2, 1, 1);
INSERT INTO sold (id, date, quantity, price) VALUES (7, 2, 1, 4);
INSERT INTO sold (id, date, quantity, price) VALUES (8, 3, 1, 1);
INSERT INTO sold (id, date, quantity, price) VALUES (9, 3, 1, 2);
INSERT INTO sold (id, date, quantity, price) VALUES (10, 3, 1, 2);




Итак. первый запрос для даты 1

select sum(t_price.price) as sum from (select price.price from testing.sold LEFT JOIN testing.price ON (price.id=sold.price) where sold.date=1) as t_price;

получаем 88. 
делаем in и вставляем дату. получаем буэ

 select sold.date,sum(t_price.price) as sum from testing.sold,(select price.price from testing.sold LEFT JOIN testing.price ON (price.id=sold.price) where sold.date IN (select date.id from testing.date)) as t_price GROUP BY sold.date;


date | sum
------+-----
2 | 693
3 | 693
1 | 924
(3 rows)

А счастье было так близко. 
PM MAIL   Вверх
tzirechnoy
Дата 30.1.2009, 02:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 2
Всего: 16



Счастье было сильно ближэ (синтаксис не проверял, но идея должны быть такой):

select t_price.date, sum(t_price.price) as sum from (select price.price, sold.date from testing.sold LEFT JOIN testing.price ON (price.id=sold.price) where sold.date IN (select date.id from testing.date) as t_price GROUP BY t_price.date;


И вообще,  вложэнные запросы здесь полный overkill. 

SELECT date.id, sum(price.price*sold.quantity) 
    FROM testing.date 
              LEFT JOIN testing.sold ON sold.date=date.id
              LEFT JOIN testing.price ON sold.price=price.id
    GROUP BY date.id
    ORDER BY date.id
PM MAIL   Вверх
sneer
Дата 2.2.2009, 03:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 13.10.2008

Репутация: нет
Всего: нет



большое спасибо но второй запрос подходит только для упрощённого условия. Начальному условию которое на старте оно не подходит. Там дополнительные условия по нахождению "завтра" и суммированию его вместе. А за первый огромное человеческое спасибо
PM MAIL   Вверх
tzirechnoy
Дата 4.2.2009, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 2
Всего: 16



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


SELECT (date.date 
          + COALESCE(sold.time, '00:00:00'::time)
          - interval '4 hour')::date 
        AS operden,
       sum(price.price*sold.quantity)
   FROM testing.date
      LEFT JOIN testing.sold ON sold.date=date.id               
      LEFT JOIN testing.price ON sold.price=price.id     
   GROUP BY operden
   ORDER BY operden
PM MAIL   Вверх
sneer
Дата 5.2.2009, 02:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 13.10.2008

Репутация: нет
Всего: нет



это явно компактнее моего угрёбища не могли бы вы разьяснить что вы делаете в новом для меня вызове COALESCE я понимаю только примерно
у меня всё это закончилось вот таким чудовищем (((
Код


select t_pricez.*,y_pricez.*, sum (t_pricez.evn_sum+y_pricez.sum) as a_sum from ( SELECT t_price.date_id as evn_date_id,t_price.date as evn_date,sum(t_price.retail) AS evn_sum
   FROM ( SELECT price.retail, sold.date_id, date.date
           FROM "trim".sold
   LEFT JOIN "trim".goods ON sold.goods_id = goods.id
   LEFT JOIN "trim".price ON goods.price_id = price.id
   LEFT JOIN "trim".date ON sold.date_id = date.id
    WHERE (sold.date_id IN ( SELECT DISTINCT sold.date_id
     FROM "trim".sold
      LEFT JOIN "trim".date ON sold.date_id = date.id
      WHERE sold."time" > '22:00:00'::time without time zone AND sold."time" < '23:59:59'::time      without time zone))
   AND sold."time" > '22:00:00'::time without time zone AND sold."time" < '23:59:59'::time without time zone ) AS t_price
  GROUP BY t_price.date, t_price.date_id) AS t_pricez 
  LEFT JOIN ( SELECT y_price.date_id, y_price.date, sum(y_price.retail) AS sum
   FROM ( SELECT price.retail, sold.date_id, date.date
           FROM "trim".sold
      LEFT JOIN "trim".goods ON sold.goods_id = goods.id
   LEFT JOIN "trim".price ON goods.price_id = price.id
   LEFT JOIN "trim".date ON sold.date_id = date.id
  WHERE (sold.date_id IN ( SELECT DISTINCT sold.date_id
    FROM "trim".sold
   LEFT JOIN "trim".date ON sold.date_id = date.id
  WHERE sold."time" > '00:00:00'::time without time zone AND sold."time" < '04:59:59'::time without time zone
  ORDER BY sold.date_id)) AND sold."time" > '00:00:00'::time without time zone AND sold."time" < '04:59:59'::time without time zone) y_price
  GROUP BY y_price.date, y_price.date_id ) as y_pricez ON (y_pricez.date=t_pricez.evn_date+1) GROUP BY t_pricez.evn_date_id,t_pricez.evn_date,t_pricez.evn_sum,y_pricez.date_id,y_pricez.date,y_pricez.sum; 


Вопрос перерос из того как делать в как сделать правильно

Это сообщение отредактировал(а) sneer - 5.2.2009, 03:15
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0858 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.