Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > PostgreSQL: суммировать от 12:00 до 11:59(сл. дня)


Автор: sneer 28.1.2009, 23:30
есть простенькая структура бд.
Продаём товар. Основная таблица 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, 02:30
мне тут немножко поправили заголовок время там чуток не правильно а так суть верна. найти сумму по каждой дате из второго запроса. Сумма находится первым запросом.Фокусы с датой можно пока убрать вообще. 
updt похоже суть вопроса правильно применить IN и JOIN вот только как...

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

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

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

Автор: sneer 30.1.2009, 01:11
Упростил всё что бы нагляднее.
три таблицы 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)

А счастье было так близко. 

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

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

Автор: sneer 2.2.2009, 03:45
большое спасибо но второй запрос подходит только для упрощённого условия. Начальному условию которое на старте оно не подходит. Там дополнительные условия по нахождению "завтра" и суммированию его вместе. А за первый огромное человеческое спасибо

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


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

Автор: sneer 5.2.2009, 02:54
это явно компактнее моего угрёбища не могли бы вы разьяснить что вы делаете в новом для меня вызове 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; 


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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)