Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

Помогите с SQL-запросом   Найти похожие ветки 

 
ProgRAMmer Dimonych ©   (2012-10-18 13:57) [0]

Есть три таблицы:

- Products (prID, prDisplayName, ...)
- Operations (opID, opDate, ...)
- OperationItems (oifkOperation, oifkProduct, oiAmount, oiPrice)

Речь идёт о продуктовом складе. В Products перечисляются все продукты, с которыми работает склад. Каждой строке в Operations соответствует приезд грузовика с продуктами. Что именно привёз грузовик - это строки OperationItems с соответствующим oifkOperation.

"Для замыслов каких-то непонятных" по этим трём таблицам нужно делать выборку информации по каждому из продуктов. При этом хлеб за 100 рублей и хлеб за 150 рублей должны учитываться отдельно. Информация по каждому "продукт A по цене B" нужна следующая:

- общее количество продукта на складе;
- количество продукта за вчерашний день;
- величина последнего поступления продукта (за один день может быть несколько поступлений);
- и т.п.

Вся информация должна в итоге стать одним резалт-сетом.

Для первых двух пунктов м.б. через "как обычно", но добился выборки:

SELECT `stoOperationItems`.`oifkProduct` AS prID,
 SUM(`stoOperationItems`.`oiAmount`) AS prLeft,
 SUM(IF(`stoOperations`.`opDateTime` = DATE_SUB(UTC_DATE(), INTERVAL 1 DAY), `stoOperationItems`.`oiAmount`, 0)) AS prYesterday,
 `stoProducts`.`prDisplayName` AS prDisplayName
FROM `stoOperationItems`
 INNER JOIN `stoProducts` ON `stoProducts`.`prID` = `stoOperationItems`.`oifkProduct`
 INNER JOIN `stoOperations` ON `stoOperations`.`opID` = `stoOperationItems`.`oifkOperation`
GROUP BY `stoOperationItems`.`oifkProduct`, `stoOperationItems`.`oiPrice`;


Проблема в выборке последнего поступления товара: как вкрутить это в этот же запрос?

P.S. Рекомендации по оптимизации запроса также приветствуются.


 
Компромисс ©   (2012-10-18 14:01) [1]

Никак. Если надо по каждому продукту, то никакой группировки быть не должно.


 
Игорь Шевченко ©   (2012-10-18 14:01) [2]

СУБД конечно же DB2 ?


 
ProgRAMmer Dimonych ©   (2012-10-18 14:06) [3]

> [2] Игорь Шевченко ©   (18.10.12 14:01)

Упс, собирался же написать.

MySQL


 
Компромисс ©   (2012-10-18 14:07) [4]

Нет, вру. Можно.
Надо вытаскивать amount from items where price= and product= and operationId = (select operationId where operDate = (select max(operDate) from operation where price= and product=))


 
ProgRAMmer Dimonych ©   (2012-10-18 14:16) [5]

> [4] Компромисс ©   (18.10.12 14:07)

Самый вложенный подзапрос: поля price и product - они в items, а не в operations. Стало быть ещё JOINить придётся? Или можно в обход?


 
Компромисс ©   (2012-10-18 14:46) [6]

ProgRAMmer Dimonych ©   (18.10.12 14:16) [5]

Да, получается придется joinить.


 
Компромисс ©   (2012-10-18 14:49) [7]

Можно еще попробовать через
from operations A
where not exists (select 1 from operations MO join items on ... where product= and price= and MO.operDate  > A.operDate)


 
ProgRAMmer Dimonych ©   (2012-10-18 15:04) [8]

Пока изобразил вот таким куском:

SELECT ...,
 (
  SELECT `oiAmount`
  FROM `stoOperationItems`
  WHERE `oifkProduct` = prID
   AND `oiPrice` = prPrice
   AND `oifkOperation` =
   (
    SELECT `opID`
    FROM `stoOperations`
     INNER JOIN `stoOperationItems` ON `stoOperationItems`.`oifkOperation` = `stoOperations`.`opID`
    WHERE `stoOperationItems`.`oifkProduct` = prID
     AND `stoOperationItems`.`oiPrice` = prPrice
    ORDER BY `stoOperations`.`opDateTime` DESC, `stoOperations`.`opID` DESC
    LIMIT 1
   )
  LIMIT 1
 ) AS prLast,
...


Вроде работает, но замечания и предложения по-прежнему принимаются.


 
Компромисс ©   (2012-10-18 15:09) [9]

Если СУБД такое поддерживает, то один вложенный select лишний. Можно сразу брать amount, а сортировать по operDate


 
ProgRAMmer Dimonych ©   (2012-10-18 15:47) [10]

> [9] Компромисс ©   (18.10.12 15:09)

Да, действительно. Спасибо за подсказку. Упростил:

SELECT `stoOperationItems`.`oifkProduct` AS prID,
 `stoOperationItems`.`oiPrice` AS prPrice,
 SUM(`stoOperationItems`.`oiAmount`) AS prLeft,
 SUM(IF(`stoOperations`.`opDateTime` = DATE_SUB(UTC_DATE(), INTERVAL 1 DAY) AND `stoOperations`.`opType` = 1, -`stoOperationItems`.`oiAmount`, 0)) AS prYesterday,
 (
  SELECT `oiAmount`
  FROM `stoOperationItems`
   INNER JOIN `stoOperations` ON `stoOperationItems`.`oifkOperation` = `stoOperations`.`opID`
  WHERE `oifkProduct` = prID
   AND `oiPrice` = prPrice
  ORDER BY `stoOperations`.`opDateTime` DESC, `stoOperations`.`opID` DESC
  LIMIT 1
 ) AS prLast,
 `stoProducts`.`prDisplayName` AS prDisplayName
FROM `stoOperationItems`
 INNER JOIN `stoProducts` ON `stoProducts`.`prID` = `stoOperationItems`.`oifkProduct`
 INNER JOIN `stoOperations` ON `stoOperations`.`opID` = `stoOperationItems`.`oifkOperation`
GROUP BY `stoOperationItems`.`oifkProduct`, `stoOperationItems`.`oiPrice`;


Ещё один вопрос: в подзапросе есть INNER JOIN с stoOperations. Попробовал его закомментировать - вроде всё отработало корректно. Можно ли безопасно убрать этот JOIN, опираясь на то, что он есть в основном запросе? Или мне просто повезло с тестовыми данными таблицы?


 
Компромисс ©   (2012-10-18 15:56) [11]


> Или мне просто повезло с тестовыми данными таблицы?


Просто повезло.

Я бы переместил Operations из основного запроса в запрос по yesterday.
Точнее, даже не так. У меня бы внеший запрос состоял только из Product. Группировка  нужна только для yesterday


 
Компромисс ©   (2012-10-18 15:58) [12]

Хотя и для суммы тоже...


 
картман ©   (2012-10-18 16:53) [13]


> Я бы переместил Operations из основного запроса в запрос
> по yesterday.

а я бы убрал этот оба подзапроса


 
ProgRAMmer Dimonych ©   (2012-10-18 16:59) [14]

> [13] картман ©   (18.10.12 16:53)

???


 
картман ©   (2012-10-18 18:59) [15]

подзапрос перенести во FROM


 
картман ©   (2012-10-18 19:03) [16]

вот это:

(
 SELECT `oiAmount`
 FROM `stoOperationItems`
  INNER JOIN `stoOperations` ON `stoOperationItems`.`oifkOperation` = `stoOperations`.`opID`
 WHERE `oifkProduct` = prID
  AND `oiPrice` = prPrice
 ORDER BY `stoOperations`.`opDateTime` DESC, `stoOperations`.`opID` DESC
 LIMIT 1
) AS prLast,

сделать производной таблицей:
(
 SELECT `oiAmount`
 FROM `stoOperationItems`
  where даты_поступления IN (выбрать максимальные даты сгруппированные по товарам, ценам)
) zzz
и выбирать max(zzz.oiAmount)



Страницы: 1 вся ветка

Текущий архив: 2013.03.22;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.05 c
15-1352139743
Pavia
2012-11-05 22:22
2013.03.22
Файлы совместимости


2-1346616136
ankazh
2012-09-03 00:02
2013.03.22
Сводная таблица


15-1346788263
AV
2012-09-04 23:51
2013.03.22
Запретить пользоваться сайтами, кроме явно разрешенных


1-1300455452
TStas
2011-03-18 16:37
2013.03.22
Как получить версию Экселя?


15-1344500626
Прогер
2012-08-09 12:23
2013.03.22
XML в Дельфи 7.