Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Требуется помощь в создании запроса.  (Прочитано 44698 раз)
0 Пользователей и 10 Гостей смотрят эту тему.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« : 20-05-2009 20:31 » 

Запрос на PostgreSQL
Имееются таблицы:
заказы; поля: номер,  работник_оформивший_заказ, дата_размещения, дата_исполнения, номер_товара, кол-во_заказанного_товара. (В одном заказе может быть только один товар)
поставки; поля: номер,  дата_поставки.
накладные; поля: номер_поставки, номер_товара, кол-во_поставленного_товара. (В одной накладной может быть только один товар).
Необходимо вывести:
Для каждого заказа - номер_товара, количество_заказанного_товара, дата_исполнения, количество товара в наличии на дату исполнения. Упорядочить по дате исполнения и наименованию товара.

Заранее спасибо.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 21-05-2009 07:26 » 

Больше всего меня радует вот этот шаблон:
Цитата
Требуется помощь
Дано:...
Нужно:...
Заранее спасибо.
Стандартная форма заказа Отлично
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #2 : 21-05-2009 19:03 » 

Простите, не поняла юмора...
Что значит: форма заказа?
Если вы имеете ввиду, что данная помощь оказывается платно, то я готова заплатить.
Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #3 : 21-05-2009 19:24 » 

Дорогая Linlees, с этого и надо начинать. Просто есть существенная разница между "помогите" и "сделайте за меня". В названии темы у тебя стоит "помощь", что подразумевает под собой, что ты что-то сделала сама, но это частично или полностью не работает. Значит надо это сделанное показать и попросить помощь, которая будет получена ессно бесплатно. Это основная философия нашего форума. Содержание же темы сводится к простой формулировки задания. В чём именно требуется помощь - не понятно. Это вводит в заблуждение.

Поэтому надо просто называть вещи своими именами не стесняясь, Сразу оговорить условия, сроки (это тоже важно) или срочность исполнения уже теперь ЗАКАЗА, а не ПОМОЩИ и тд. При наличии желающих с достаточным количеством свободного времени я думаю решение будет найдено, при полном непротивлении сторон.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #4 : 21-05-2009 20:19 » 

Вот то, что делала я сама:
SELECT O_DATE AS DATA_ZAKAZA, P_NAME AS TOVAR, SUM(ZAKAZ_NUM) AS ZAKAZANO, SUM(OSTATOK) AS V_OSTATKE
FROM (

SELECT q1.ddate AS O_DATE, q1.PROD_NAME AS P_NAME, q1.number AS ZAKAZ_NUM, (q2.number - q1.number) AS OSTATOK
FROM (
   SELECT p.item AS PROD_NAME, p.id AS product, o.number AS number, o.execution_date AS ddate
   FROM
      orders AS o JOIN products AS p ON(o.product_id=p.id)
   ORDER BY o.execution_date) AS q1
   

   JOIN

      (SELECT c.product_id AS product, d.date AS ddate, SUM(c.number) AS number
      FROM
         consignment AS c JOIN delivery AS d ON(c.delivery_id=d.id)
      GROUP BY d.date, c.product_id
      ORDER BY d.date,c.product_id) AS q2

   ON(q1.product=q2.product AND q1.ddate > q2.ddate)   
ORDER BY q1.ddate, q1.PROD_NAME

   ) AS Q
GROUP BY Q.O_DATE, Q.P_NAME
ORDER BY Q.O_DATE, Q.P_NAME;

consignment - накладная, order - заказ, delivery - поставка.

Но я уверена, что это не правильно.  Мне кажется, что к данному запросу нужно делать какую то дополнительную процедуру, но т.к. мои знания ограничиваются общим курсом БД, преподаваемом в ВУЗе, я прошу помощи.
Подскажите хотя бы в каком направлении двигаться.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 22-05-2009 06:13 » 

Цитата: LinLees
ЗАКАЗЫ: Номер,  Работник оформивший заказ, Дата размещения, Дата исполнения, Номер товара, Количество заказанного товара.

ПОСТАВКИ: Номер,  Дата поставки.

НАКЛАДНЫЕ: Номер поставки, Номер товара, Количество поставленного товара.

Цитата: LinLees
Необходимо вывести:

Для каждого заказа: Номер товара, Количество заказанного товара, Дата исполнения, количество товара в наличии на дату исполнения.

Упорядочить по дате исполнения и наименованию товара.
Вот скажи, как по-твоему, достаточно ли информации указано в "Дано", чтобы выполнить "Необходимо"?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 22-05-2009 06:25 » 

Цитата
Для каждого заказа - номер_товара, количество_заказанного_товара, дата_исполнения, количество товара в наличии на дату исполнения. Упорядочить по дате исполнения и наименованию товара.
Код:
   SELECT p.item AS PROD_NAME, p.id AS product, o.number AS number, o.execution_date AS ddate
   FROM
      orders AS o JOIN products AS p ON(o.product_id=p.id)
   ORDER BY o.execution_date)

Выбрали продукт и дату исполнения

Кстати ORDER BY здесь не нужен, потому как у тебя далее будет идти join  и, кроме того, это у тебя подзапрос
Код:
      SELECT c.product_id AS product, d.date AS ddate, SUM(c.number) AS number
      FROM
         consignment AS c JOIN delivery AS d ON(c.delivery_id=d.id)
      GROUP BY d.date, c.product_id
      ORDER BY d.date,c.product_id
здесь то же лишний order by

Но принципиальная ошибка, ведь ты используешь объединение запросов
Сравни:
   SELECT p.item AS PROD_NAME, p.id AS product, o.number AS number, o.execution_date AS ddate
   SELECT c.product_id AS product, d.date AS ddate, SUM(c.number) AS number
И скажи, почему я обратил на это внимание?
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #7 : 22-05-2009 10:40 » 


Вот скажи, как по-твоему, достаточно ли информации указано в "Дано", чтобы выполнить "Необходимо"?

Ивините,  если чего то не хватает, то скажите чего, я дополню. Но я перечислила все поля, которые содержат эти таблицы.


Сравни:
   SELECT p.item AS PROD_NAME, p.id AS product, o.number AS number, o.execution_date AS ddate
   SELECT c.product_id AS product, d.date AS ddate, SUM(c.number) AS number
И скажи, почему я обратил на это внимание?

Возможно потому, что эти запросы нельзя объединять?
Если я права, то объясните, пожалуйста, почему, т.к. повторюсь - мои знания очень ограничены.

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

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #8 : 22-05-2009 11:17 » 

Linlees, Что делает SELECT q1.ddate?
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #9 : 22-05-2009 11:25 » 

Выводит дату исполнения заказа...
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 22-05-2009 11:26 » 

Цитата
Возможно потому, что эти запросы нельзя объединять?
Почему?
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #11 : 22-05-2009 11:31 » 

Почему?

А вот этого я уже не знаю:(
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 22-05-2009 12:02 » 

Давай с самого начала (потому как я тут такого ща наговорил, что самому стыдно - union с join перепутал)  разгребать постепенно, а не сразу ваять большой запрос
1. Выбрать
    Заказ, Номер_товара, количество_заказанного_товара, дата_исполнения
2. Выбрать
   номер_товара, количество_поставленного_товара

3. Выбрать
Количество_товара_в наличии
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #13 : 22-05-2009 12:12 » 

1. SELECT id, product_id, number, execution_date FROM orders

2. SELECT product_id, number FROM consignment

3. вот тут у меня загвоздка: я не знаю как это можно вычислить.
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 22-05-2009 12:49 » 

Linlees, ну а как ты посчитала бы без базы, а на бумажке?
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #15 : 22-05-2009 13:06 » 

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

Код:
 SELECT o.product_id, COUNT(c.number), COUNT(o.number) 
FROM orders AS o
JOIN consignment AS c ON c.product_id=o.product_id)
GROUP BY o.product_id;
   - что-то подобное

а вот как это привязать к определенной дате которая заранее неизвестна ....
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 22-05-2009 13:16 » 

а если так?
Код:
SELECT o.product_id, ( COUNT(c.number) - COUNT(o.number) )
FROM orders AS o
JOIN consignment AS c ON c.product_id=o.product_id)
GROUP BY o.product_id;
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #17 : 22-05-2009 13:19 » 

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

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 22-05-2009 13:22 » 

А теперь
1. Выбрать
    Заказ, Номер_товара, количество_заказанного_товара,
где дата_исполнения меньше 01/01/2009

2. Выбрать
   номер_товара, количество_поставленного_товара, дата_поставки
где дата_поставки меньше 01/01/2009
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #19 : 22-05-2009 13:31 » 

1.SELECT product_id, number FROM orders WHERE (execution_date > 2009-01-01);

2.SELECT c.product_id, c.number, d.date FROM consignment AS c JOIN delivery AS d ON (c.product_id=d.product_id) WHERE (d.date > 2009-01-01); - возможно здесь нужен GROUP BY...
« Последнее редактирование: 22-05-2009 13:35 от Linlees » Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #20 : 22-05-2009 13:35 » 

SELECT c.product_id, c.number, d.date
     FROM consignment AS c
      JOIN delivery AS d
on (c.product_id=d.product_id) WHERE (d.date < 2009-01-01)

А зачем group by? У тебя здесь есть агрегатные функции?

МЕНЬШЕ!
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #21 : 22-05-2009 13:40 » 

Ой, простите, это моя невнимательность.

Кажется в голове начинает проясняться, но надо проверить на практике. Сейчас приеду домой, буду проверять.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 22-05-2009 13:52 » 

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

Сейчас же твои попытки больше похожи на попытку получить результат шаманскими гаданиями над кодом, который ты не очень хорошо понимаешь.
Цитата: Linlees
ну если честно, я хотела так написать, но подумала, вдруг он так не посчитает, а проверить я к сожалению пока не могу, т.к. постгреса на работе нету
"Вдруг" не бывает. Это ж не гадание на картах.

Возьми по 5 записей с каждой таблицы (лишь бы они сочетались по датам и связям), и на них подбери, какие нужны операции для получения результата:
1) объединение таблиц (и способ объединения - FROM ... JOIN),
2) фильтрация строк (WHERE),
3) группировка (GROUP BY),
4) фильтрация групп (HAVING),
5) отбор столбцов (SELECT), вычисление значений (в том числе функции COUNT, SUM, AVG и т.д.), ликвидация повторов строк (DISTINCT)
6) сортировка (ORDER BY)
Операции применять в указанном порядке.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #23 : 22-05-2009 13:58 » 

dimka, тут есть уже сдвиги

Цитата
Кажется в голове начинает проясняться, но надо проверить на практике.
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 22-05-2009 19:13 » 

Sla, не думаю.

Начать можно с малого:
Цитата: Linlees
сосчитать общее количество товари, поставленного на эту дату
Это элементарно для случая, когда дата задаётся параметром запроса. Но вот случай, когда нужно считать накопительную сумму - это уже на догадливость.

Пока опустим разные товары, чтобы не добавлять группировок - отдельная тема.

Допустим, есть таблица
ГРАФИК ПЛАТЕЖЕЙ: Дата платежа, Сумма платежа.

Например:
01.04.09   20000.00
02.04.09   03742.11
03.04.09   01743.37
04.04.09   00003.37
13.04.09   01129.80
14.04.09   15000.00


Требуется написать запрос, который для каждой даты выдаёт накопительный итог:

01.04.09   20000.00
02.04.09   23742.11
03.04.09   25485.48
04.04.09   25488.85
13.04.09   26618.65
14.04.09   41618.65
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #25 : 22-05-2009 20:04 » 

select field_data, (select sum(field_sum) from table where field_data<=t.field_data) itog
from table t
order by field_data

Не знаю, не проверял, но должно работать
А вот интересно, поможет ли это в нашем случае?
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #26 : 22-05-2009 20:30 » 

Практически не удалось посидеть подумать над запросом, результата пока никакого, последний вариант:

Код:
SELECT ord.product_id, ord.number, ord.execution_date, COUNT(ord.number) AS ostatok 
GROUP BY ord.product_id, ord.number, ord.execution_date
HAVING COUNT(ord.number)=(
SELECT (COUNT(c.number) - COUNT(o.number))
FROM orders AS o
JOIN consignment AS c ON (c.product_id=o.product_id)
JOIN delivery AS d ON (c.delivery_id=d.id)
GROUP BY o.product_id, d.date, o.execution_date
HAVING (d.date<ord.execution_date AND o.execution_date<ord.execution_date)
)
FROM orders AS ord
ORDER BY ord.product_id;


Но он не работает,  выдает ошибку ERROR:  more than one row returned by a subquery used as an expression.

Завтра буду разбираться, что не так.
Записан
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #27 : 23-05-2009 08:05 » 

В общем это все что у меня получилось
 
Код:
SELECT (SUM(c.number)-SUM(o.number)) 
FROM orders AS o
JOIN consignment AS c ON (c.product_id=o.product_id)
JOIN delivery AS d ON (c.delivery_id=d.id)
GROUP BY o.product_id, d.date, o.execution_date
HAVING (d.date<'2009-04-01' AND o.execution_date<'2009-04-01')
;
  -это внутренний  подзапрос, с COUNT он не работает, выдает одни нули. А с SUM работает - проверила по значениям из таблицы. Выдает столбец с разницей поставленного и заказанного на эту дату.
К внешнему запросу где нужно выбрать номер_продукта и дату_исполнения мне его никак не прикрутить.
Все время пишет эту ошибку, что подзапрос выдает более чем один ряд. Где я ошиблась?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #28 : 23-05-2009 08:18 » 

Цитата: Sla
select field_data, (select sum(field_sum) from table where field_data<=t.field_data) itog
from table t
order by field_data
Да, это типовое решение. Я только не знаю, есть ли в PostgreSQL поддержка подзапросов, которые работают в секции SELECT.

А ты напиши решение без таких подзапросов. Чтобы. допустим, в FoxPro 2.6 под DOS работало Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Linlees
Участник

ru
Offline Offline
Пол: Женский

« Ответ #29 : 23-05-2009 22:02 » 

Я только не знаю, есть ли в PostgreSQL поддержка подзапросов, которые работают в секции SELECT.
не поддерживает, сегодня это проверила на собственном опыте.

Код:
SELECT  o.product_id, o.execution_date,  (q2.summa1-q1.summa) AS OSTATOK		
FROM (SELECT product_id,  SUM(number) AS summa
FROM orders
GROUP BY product_id
HAVING MAX(execution_date)<'2009-05-23') AS q1
JOIN
(SELECT product_id,  SUM(number) AS summa1
FROM consignment AS c  
JOIN delivery AS d ON (c.delivery_id=d.id)
GROUP BY product_id
HAVING MAX(d.date)<'2009-05-23') AS q2
ON (q1.product_id=q2.product_id)
JOIN orders AS o
ON (o.product_id=q1.product_id)
GROUP BY o.execution_date, o.product_id, q2.summa1, q1.summa
ORDER BY o.execution_date;

Осталась проблема привязки к дате_исполнения...
Записан
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines