2016-01-26 7 views
0

Я попытался найти этот форум для ответа, но не могу найти его.Mysql вычесть из другой таблицы

Моя проблема: у меня есть 3 стола. Один с товарами, один с входящими поставками и один с исходящими поставками.

Таблица называется пунктов:

id | item_name 
---------------- 
1 | Bike 
2 | Helmet 
3 | Pedal 
4 | Light 

Таблица называется вновь прибывающий:

id | item_id | quantity 
----------------------- 
1 | 2  | 5 
2 | 3  | 2 
3 | 4  | 1 
4 | 1  | 5 
5 | 2  | 4 
6 | 1  | 6 
7 | 3  | 5 

Таблица называется исходящее:

id | item_id | quantity 
----------------------- 
1 | 3  | 2 
2 | 1  | 1 
3 | 2  | 3 
4 | 3  | 4 
5 | 1  | 2 
6 | 2  | 1 
7 | 4  | 1 

То, что я хочу сделать, это получить общее количество в наличии на вычитая исходящие поставки из очереди и упорядочивая их по наименьшей сумме.

Возможно, есть лучший способ сделать это?

Это запрос, который я получил, но суммы SUM не верны. Может кто-нибудь помочь мне и объяснить, почему суммы СУММ не верны и как я могу решить это наилучшим образом?

SELECT items.id AS ID, 
     items.item_name, 
     Sum(ingoing.quantity) - Sum(outgoing.quantity) AS InStock 
FROM items 
     LEFT JOIN ingoing 
       ON ingoing.item_id = items.id 
     LEFT JOIN outgoing 
       ON outgoing.item_id = items.id 
GROUP BY ID 
ORDER BY InStock ASC 

Это результат я хочу от этого:

ID | item_name | InStock 
--------------------------- 
4 | Light  | 0 
3 | Pedal  | 1 
2 | Helmet | 5 
1 | Bike  | 8 

Что я получаю:

ID | item_name | InStock 
--------------------------- 
4 | Light  | 0 
3 | Pedal  | 2 
2 | Helmet | 10 
1 | Bike  | 16 
+2

Если вам нравится, рассмотрите следующий простой двухэтапный курс действий: 1.Если вы еще этого не сделали, предоставьте правильные инструкции CREATE и INSERT (и/или sqlfiddle), чтобы мы могли легче реплицировать проблему. 2. Если вы еще этого не сделали, укажите желаемый результирующий набор, соответствующий информации, представленной на шаге 1. – Strawberry

+0

Просьба предоставить данные теста, которые существуют в текущих таблицах. –

+0

Просьба указать, какие данные вы получаете? –

ответ

1

Это может быть легко забыть мультипликативный эффект соединения. Когда вы сталкиваетесь с проблемами, как это проверить результат присоединения, до фильтрации/группировки:

SELECT items.id, 
     items.item_name, 
     ingoing.id AS ingoing, 
     outgoing.id AS outgoing 
FROM items 
     LEFT JOIN ingoing 
       ON ingoing.item_id = items.id 
     LEFT JOIN outgoing 
       ON outgoing.item_id = items.id 

Посмотри на sqlfiddle.

Как вы можете видеть, набор результатов содержит несколько записей с одинаковыми значениями ingoing.id и несколькими записями с теми же значениями outgoing.id. Это связано с тем, что каждая входящая запись для определенного элемента соединяется с каждой исходящей записью для этого же элемента: таким образом, в наборе результатов есть 4 педали (2 входящих x 2 исходящих) и т. Д.

Агрегирование каждой таблицы по позиции до присоединения (и, таким образом, гарантируя, что есть только одна запись за единицу на каждой стороне соединения) будет добиться того, что вы после:

SELECT items.id AS ID, 
     items.item_name, 
     ingoing.quantity - outgoing.quantity AS InStock 
FROM items 
     LEFT JOIN (
     SELECT item_id AS id, SUM(quantity) AS quantity 
     FROM  ingoing 
     GROUP BY item_id 
     ) AS ingoing USING (id) 
     LEFT JOIN (
     SELECT item_id AS id, SUM(quantity) AS quantity 
     FROM  outgoing 
     GROUP BY item_id 
     ) AS outgoing USING (id) 
ORDER BY InStock ASC 

Посмотри на sqlfiddle.

Обратите внимание, что ваша проблема была бы значительно упрощена, если бы была только одна базовая таблица движения запаса, с положительными величинами, указывающими движения в одном направлении и отрицательные количества, указывающие движения в противоположном направлении: тогда простое групповое суммирование целого таблица даст желаемые результаты.

+0

Очень хорошее объяснение! Это, похоже, решает мою проблему, спасибо! То, что я вижу другую проблему сейчас, я не знаю, как правильно использовать JOIN, потому что, если я добавлю еще один элемент, и он имеет только входящее количество, а не наш текущий, он не отображает количество, просто NULL. Вы знаете, как это исправить? Здесь вы получили скрипку: [link] (http://sqlfiddle.com/#!9/7ead2/1) – cybrz

+0

@cybrz: Вы можете использовать 'IFNULL (outgoing.quantity, 0)' в списке выбора/вычитании. – eggyal

+0

Спасибо @eggyal Но проблема в том, что элемент может иметь значение (исходящее от входящего количества), и если theres no исходящее количество показывает NULL. Я понимаю, что вы имеете в виду, но я не думаю, что это работает в этом сценарии. – cybrz

0

Попробуйте этот запрос:

SELECT items.id AS ID, items.item_name, (SELECT SUM(quantity) from ingoing 
WHERE ingoing.item_id = items.id) - (SELECT SUM(quantity) from outgoing WHERE 
outgoing.item_id = items.id) AS InStock FROM items ORDER BY InStock ASC; 
Смежные вопросы