2015-03-26 4 views
0

Это моя ситуация.SQL-запрос left join where where

У меня есть 3 таблицы

Orders 
- id status deleted 

Order Lines 
- related_id related_model quantity 

Products 
- id code price price_purchase 

Я хочу, чтобы создать список с all products. amount of times they are purchased и sum of the gross margin (цена - цена_покупка). Он должен использовать только строки заказов с related model set to 'products'. А во-вторых, он должен только выбрать заказы с status set to 'paid, processing, sent, ready_for_pickup or picked_up' и порядка not deleted.

Так что это будет результат я хочу:

id | code | purchases | value 
------------------------------- 
1 | code1 | 7   | 57,05 
2 | code2 | 122  | 254,98 
3 | code3 | 0   | 0,00 

Это SQL запрос у меня есть до сих пор:

SELECT p.id, p.code, IFNULL(SUM(sol.quantity) , 0) as purcahses,  
sum((p.price - p.price_purchase) * quantity) as value 
FROM products p 
LEFT JOIN shop_orders_lines sol ON sol.related_id = p.id 
AND sol.related_model = 'products' 
LEFT JOIN shop_orders so ON so.id = sol.order_id 

WHERE so.status IN ('paid', 'processing', 'sent', 'ready_for_pickup', 'picked_up') 
AND so.deleted = 0 
GROUP BY p.id 

Он возвращает правильные данные. Но не все проблемы. Это моя проблема. Я много разных методов, таких как подзапросы и другие методы, но не могу решить проблему. Я знаю, что проблема в моем LEFT-соединении, но не знаю решения моей проблемы.

Я использую MySQL Workbench.

Любая помощь приветствуется.

+0

Помимо: 'related_model' столбец указывает, что ваша схема нарушает [принцип ортогональной конструкции] (http://en.wikipedia.org/wiki/Principle_of_orthogonal_design). – eggyal

+0

Ваше описание того, что вы хотите, несовместимо с остальной частью того, что вы говорите. Вы хотите * все * продукты? Или отфильтрованы? Нужно ли им приказ вернуть их? Нужно ли им быть частью очереди заказов, которую нужно вернуть? Пожалуйста, подтвердите свой желаемый результат в очень четких выражениях, чтобы кто-то мог вам помочь – Tim

+0

Тим, мое описание довольно ясное. Поэтому я хочу, чтобы все продукты имели свою валовую маржу и объем покупок. Так что, если они еще не были куплены до того, как это, вероятно, не будет для него. Поэтому он должен показывать 0 в последних двух столбцах – Bram

ответ

2

Ваш присоединяется неверны. Вам необходимо идентифицировать строки заказов, которые следует рассматривать отдельно от и до формирования ЛЕВЫЙ ПРИСОЕДИНЕНИЕ с деталями продукта. Вид рядный может помочь:

SELECT 
    p.id, 
    p.code, 
    IFNULL(SUM(ordered_item.quantity) , 0) as purchases ,  
    sum((p.price - p.price_purchase) * ordered_item.quantity) as value 
    FROM 
    products p 
    LEFT JOIN (
     SELECT 
     sol.related_id AS related_id, 
     sol.quantity AS quantity 
     FROM 
     shop_orders_lines sol 
     INNER JOIN shop_orders so 
      ON so.id = sol.order_id 
     WHERE 
     so.status IN ('paid', 'processing', 'sent', 'ready_for_pickup', 'picked_up') 
      AND so.deleted = 0 
      AND sol.related_model = 'products' 
    ) ordered_item 
     ON ordered_item.related_id = p.id 
GROUP BY p.id 
+0

Да, это сделал трюк. Благодаря! – Bram

1

Переместить внешние условия столовый из КУДА ПО, иначе OUTER JOIN работает как обычный INNER JOIN:

SELECT p.id, p.code, IFNULL(SUM(sol.quantity) , 0) as purcahses,  
sum((p.price - p.price_purchase) * quantity) as value 
FROM products p 
LEFT JOIN shop_orders_lines sol ON sol.related_id = p.id 
AND sol.related_model = 'products' 
LEFT JOIN shop_orders so ON so.id = sol.order_id AND 
so.status IN ('paid', 'processing', 'sent', 'ready_for_pickup', 'picked_up') 
AND so.deleted = 0 
GROUP BY p.id 

ли p.id весь первичный ключ для этой таблицы? Если нет, вам нужно выяснить, как обращаться с p.code. (Либо список в GROUP BY, или использовать в качестве аргумента функции совокупного.)

Другая попытка:

SELECT p.id, p.code, IFNULL(SUM(sol.quantity) , 0) as purcahses,  
sum((p.price - p.price_purchase) * quantity) as value 
FROM products p 
JOIN shop_orders_lines sol ON sol.related_id = p.id 
AND sol.related_model = 'products' 
WHERE EXISTS (select 1 from shop_orders so 
       where so.id = sol.order_id 
       AND so.status IN ('paid', 'processing', 'sent', 'ready_for_pickup', 'picked_up') 
       AND so.deleted = 0) 
GROUP BY p.id 
+2

Он не работает. Он возвращается ко многим покупкам. Он возвращает все покупки и игнорирует статус. И да, p.id является основным ключом для продуктов – Bram

+0

Какова цель второй LEFT JOIN? Не можете ли вы переместить эту логику/условие в EXISTS? – jarlh

+0

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

Смежные вопросы