0

I'm trying to get a list of products order by the amount sold and by date. I also want to display the products that haven't been sold in the list so I tried doing a subquery first but MYSQL is giving me this message:

Operand should contain 1 column(s)

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')

The subquery did not work, So i tried using LEFT OUTER JOIN as suggested by another member with this query:

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

But this query with LEFT OUTER JOIN is giving me the list of product sold only, what I want is to also show the products that haven't been sold in the list.

Here is the schema used sqlfiddle.com/#!2/967ee

4

1 回答 1

1

此查询将起作用,将SELECTproducts 表中的更多列添加到SELECTandGROUP 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_approvedand而不是 sales 表中的值,则此查询会简单得多。product_sold_approved_timeWHERE

You LEFT JOIN product_soldLEFT 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 子句的这一半,因此我们过滤掉不需要的销售。

最后,我们得到一个结果集,其中包含没有任何销售的所有记录 + 满足您条件的所有产品/产品销售/销售记录。然后我们可以按 product_id 分组并对剩下的内容求和。

我的 SQL 中有IFNULLs ,这是因为如果你对很多值求和,其中一些可能是NULL,如果单个值是sNULL的结果。通过将任何值转换为 a 来防止这种情况发生。, . 但是,经过反思,我可能不需要查询 - 删除它们,您应该注意到更改。SUMNULLIFNULL(column,0)NULL01 + NULL = NULL1 + 0 = 1

于 2013-12-04T23:51:24.387 回答