Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

Помогите с 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.062 c
4-1259658224
sniknik
2009-12-01 12:03
2013.03.22
Получить список групп текущего юзера/общий


15-1350648132
toto
2012-10-19 16:02
2013.03.22
C# GridView


15-1353500246
ЕщеОдинКакжеНадоели
2012-11-21 16:17
2013.03.22
Документация к программе.


15-1334692803
ДимкаНа
2012-04-18 00:00
2013.03.22
Как называется электромагнитный поршень?


15-1331419316
Дмитрий С
2012-03-11 02:41
2013.03.22
Шифрование диска. Теоретический вопрос.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский