2013-12-04 3 views
0

Я пытаюсь получить список заказов на продукцию по количеству проданных и по дате. Я также хочу, чтобы отобразить продукты, которые не были проданы в списке, так что я пытался делать подзапрос первый, но MYSQL дает мне это сообщение:Проблема с LEFT OUTER JOIN

Операнд должен содержать 1 столбец (ы)

SELECT product.product_id, 
     product.product_brand_id, 
     product.product_model_id, 
     product.product_subcategory_id, 
     product.product_retail_price, 
     product.product_wholesale_price 
FROM product 
WHERE product.product_subcategory_id = $subcategory_id 
AND (SELECT SUM(product_sold.product_quantity) AS product_quantity_sold, 
      SUM(product_sold.product_total_price) AS total_price_sold 
    FROM product 
    INNER JOIN product_sold 
     ON product.product_id = product_sold.product_id 
    INNER JOIN sales 
     ON sales.sales_id = product_sold.product_sales_id 
    WHERE sales.sales_approved = '1' 
     AND sales.sales_approved_time > '$start_timestamp' 
     AND sales.sales_approved_time < '$end_timestamp') 

подзапрос не работает, поэтому я попытался использовать LEFT OUTER JOIN как предложил другой член с этим запросом:

SELECT product.product_id, 
     product.product_brand_id, 
     product.product_model_id, 
     product.product_subcategory_id, 
     product.product_retail_price, 
     product.product_wholesale_price, 
     SUM(product_sold.product_quantity) AS product_quantity_sold, 
     SUM(product_sold.product_total_price) AS total_price_sold 
FROM product 
LEFT OUTER JOIN product_sold ON product.product_id = product_sold.product_id 
          AND product.product_subcategory_id = $subcategory_id 
LEFT OUTER JOIN sales ON sales.sales_id = product_sold.product_sales_id 
WHERE sales.sales_approved = '1' 
    AND sales.sales_approved_time > '$start_timestamp' 
    AND sales.sales_approved_time < '$end_timestamp' 
GROUP BY product.product_id 
ORDER BY SUM(product_sold.product_quantity) DESC 

Но этот запрос с LEFT OUTER JOIN дает мне список продукции продается только то, что я хочу, чтобы также показать продуктов, которые не были проданы в списке.

Вот схема, используемая sqlfiddle.com/#!2/967ee

+0

Насколько я могу судить, простая 'LEFT JOIN' - это то, что вам нужно. – OGHaza

+0

Если я сделаю ЛЕВЫЙ ПРИСОЕДИНЯЮ, я получаю тот же результат, если появятся только проданные товары. – bmacuer

+0

Я бы сказал, что LEFT OUTER JOIN должен работать ... (я не понимаю разницы между product_sold и btw продаж). Может быть, вы можете предоставить используемую схему? – luckylwk

ответ

1

Этот запрос будет работать, более SELECT столбцов из таблицы продуктов добавить их к обоим SELECT и GROUP BY положения:

SELECT p.product_id 
    ,SUM(IFNULL(ps.product_quantity,0)) AS product_quantity_sold 
    ,SUM(IFNULL(ps.product_total_price,0)) AS total_price_sold 
FROM product p 
LEFT JOIN product_sold ps ON p.product_id = ps.product_id 
LEFT JOIN sales s ON ps.product_sales_id = s.sales_id 
WHERE p.product_subcategory_id = $subcategory_id 
    AND (s.sales_id IS NULL 
     OR (s.sales_approved = '1' 
      AND s.sales_approved_time > '$start_timestamp' 
      AND s.sales_approved_time < '$end_timestamp' 
     ) 
     ) 
GROUP BY p.product_id 
ORDER BY SUM(IFNULL(ps.product_quantity,0)) DESC 

Объяснение

Этот запрос был бы намного проще, если бы вы могли бы использовать product_sold_approved и product_sold_approved_time в предложении WHERE вместо значений из таблицы продаж.

Вы LEFT JOIN product_sold, LEFT JOIN означает, что вы держите все записи из таблицы products, и те, которые были проданы получат присоединились к каждому из product_sold записей. Затем вы делаете то же самое для таблицы sales.

На этом этапе у вас есть много строк, которые являются product + product_sold + sales, но у вас также есть все непроданные продукты product + NULL + NULL. Вам нужно отфильтровать все объединенные записи, где соответствующие поля сбыта не соответствуют вашим критериям, но вам нужно оставить все записи, которые не смогли присоединиться в одиночку.

Для этого у вас есть предложение WHERE, которое касается каждого набора записей отдельно. WHERE (condition A) OR (condition B).

Условие A касается наших непроданных продуктов, WHERE s.sales_id IS NULL - все записи, которые не могут присоединиться к продаже, включены в результирующий набор и не должны соответствовать другим критериям.

OR (sales_approved = 1 AND ... AND ...) записи, в которых s.sales_id не является NULL, придется передать эту половину предложения where, поэтому мы отфильтровываем нежелательные продажи.

В конце мы остаемся с результирующим набором, который содержит все записи, в которых не было продаж + все товар/товар_серии/запись продаж, соответствующая вашим критериям. Тогда мы можем просто GROUP BY product_id И SUM, что осталось.

У меня есть IFNULL с в моем SQL, это потому, что если вы суммируя множество значений, и некоторые из них могут быть NULL, если одно значение NULL то результат из SUM является NULL. IFNULL(column,0) защищает от этого путем преобразования любых значений NULL в 0. 1 + NULL = NULL, 1 + 0 = 1.HOWEVER, по отражению I, которые, вероятно, не нужны для запроса - удалите их, и вы должны заметить изменение.

+0

Если это сработает, я объясню это – OGHaza

+0

Это действительно сработало! Пожалуйста, объясните это, чтобы понять больше, спасибо! – bmacuer

+0

Без проблем, излишне длинное объяснение добавлено. – OGHaza