0

販売量と日付順で商品のリストを取得しようとしています。また、リストで販売されていない製品を表示したいので、最初にサブクエリを実行しようとしましたが、MYSQL から次のメッセージが表示されます。

オペランドには 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

4

1 に答える 1

1

このクエリは機能し、products テーブルの列をさらにと句SELECTの両方に追加します。SELECTGROUP 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

説明

sales テーブルの値の代わりに節でproduct_sold_approvedandを使用できれば、このクエリははるかに簡単になります。product_sold_approved_timeWHERE

YouLEFT JOIN product_soldは、テーブルのすべてのレコードLEFT JOINを保持することを意味し、販売されたレコードは各レコードに結合されます。次に、テーブルに対して同じことを行います。productsproduct_soldsales

したがって、この段階では、多くの行がありますが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/product_sales/sales レコードを含む結果セットが残ります。次に、product_id で GROUP BY AND SUM を実行するだけです。

SQLにIFNULLs があります。これは、多くの値を合計していて、そのうちのいくつかが である可能性がNULLあるNULLためSUMですNULL。は、任意の値を にIFNULL(column,0)変換することでこれを防ぎます。、。ただし、リフレクションでは、おそらくクエリには必要ありません-それらを削除すると、変更に気付くはずです。NULL01 + NULL = NULL1 + 0 = 1

于 2013-12-04T23:51:24.387 に答える