带有或不带有HAVING子句的MySQL COUNT查询给出相同的结果

时间:2014-07-18 11:36:41

标签: mysql sql

我遇到涉及COUNT和HAVING子句的SQL查询问题。 目的是得到所有有库存但也没有被挑选的产品的数量。为另一个客户,因此HAVING条款。

但是,当在下面的查询结尾处使用和不使用HAVING子句运行查询时,我得到与结果相同的COUNT。

为了确保COUNT结果不一样,我尝试运行查询以检查是否有产品缺货,因为所有产品都需要有库存才能使结果匹配并确认确实存在产品缺货。

SELECT
  COUNT(DISTINCT p.product_id)
FROM product p
LEFT JOIN product_variant pv
  ON pv.product_variant_id = p.product_id
LEFT JOIN depot_product_stock dps
  ON dps.product_variant_id = pv.product_variant_id
LEFT JOIN (
  SELECT pii.quantity, pii.product_variant_id
            FROM `picklist_item` pii
            WHERE pii.STATUS IN ('not picked')
  ) AS pickListNotPicked
  ON pickListNotPicked.product_variant_id = pv.product_variant_id
LEFT JOIN (
  SELECT pii.quantity, pii.product_variant_id
            FROM `picklist_item` pii
            LEFT JOIN `packing` packi ON packi.picklist_id = pii.picklist_id
            WHERE pii.STATUS IN ('picked')
            AND pii.date_picked > NOW() - INTERVAL 2 WEEK
            AND packi.picklist_id IS NULL
  ) AS pickListPicked
  ON pickListPicked.product_variant_id = pv.product_variant_id
LEFT JOIN (
  SELECT pii.quantity, pii.product_variant_id
            FROM `picklist_item` pii
            LEFT JOIN `packing` packi ON packi.picklist_id = pii.picklist_id
            WHERE packi.`status` IN ('new', 'in progress')
  ) AS pickListInProgress
  ON pickListInProgress.product_variant_id = pv.product_variant_id
WHERE p.deleted = 0
HAVING SUM(dps.physical_stock)
    - ifnull(SUM(pickListNotPicked.quantity),0)
    - ifnull(SUM(pickListPicked.quantity) ,0)
    - ifnull(SUM(pickListInProgress.quantity) ,0)
    > 0

我不知道我的查询出错了。请帮助。感谢。

2 个答案:

答案 0 :(得分:0)

我认为你不想要having条款。您的查询只返回一行。该having子句可能使其返回零行而不是一行。并且,having条款正在查看所有产品。

也许你想要一个where条款:

WHERE p.deleted = 0 AND
      (dps.physical_stock - ifnull(pickListNotPicked.quantity, 0) -
       ifnull(pickListPicked.quantity, 0)
       ifnull(pickListInProgress.quantity, 0)
      ) > 0

请注意,我更愿意将ifnull()替换为coalesce()。 (当给出选项时,我通常更喜欢ANSI标准函数。)

答案 1 :(得分:0)

我认为问题在于您要混合所有要检查的数量。

您的查询似乎是在尝试查找实际库存数量不等于各种状态数量总和的产品数量。

麻烦的是,您正在整理所有库存量并选择所有产品的数量。因此,如果任何单个产品不匹配,它将反映在HAVING子句中的检查中。

我认为你需要一个大的子查询来获取数量不匹配的所有产品ID,然后根据它进行计数。

像这样(未经测试)。

SELECT COUNT(product_id)
FROM
(
    SELECT p.product_id
    FROM product p
    LEFT JOIN product_variant pv
    ON pv.product_variant_id = p.product_id
    LEFT JOIN depot_product_stock dps
    ON dps.product_variant_id = pv.product_variant_id
    LEFT JOIN 
    (
        SELECT pii.quantity, pii.product_variant_id
        FROM `picklist_item` pii
        WHERE pii.STATUS IN ('not picked')
    ) AS pickListNotPicked
    ON pickListNotPicked.product_variant_id = pv.product_variant_id
    LEFT JOIN 
    (
        SELECT pii.quantity, pii.product_variant_id
        FROM `picklist_item` pii
        LEFT JOIN `packing` packi ON packi.picklist_id = pii.picklist_id
        WHERE pii.STATUS IN ('picked')
        AND pii.date_picked > NOW() - INTERVAL 2 WEEK
        AND packi.picklist_id IS NULL
    ) AS pickListPicked
    ON pickListPicked.product_variant_id = pv.product_variant_id
    LEFT JOIN 
    (
        SELECT pii.quantity, pii.product_variant_id
        FROM `picklist_item` pii
        LEFT JOIN `packing` packi ON packi.picklist_id = pii.picklist_id
        WHERE packi.`status` IN ('new', 'in progress')
    ) AS pickListInProgress
    ON pickListInProgress.product_variant_id = pv.product_variant_id
    WHERE p.deleted = 0
    GROUP BY p.product_id
    HAVING SUM(dps.physical_stock)
        - IFNULL(SUM(pickListNotPicked.quantity),0)
        - IFNULL(SUM(pickListPicked.quantity) ,0)
        - IFNULL(SUM(pickListInProgress.quantity) ,0)
        > 0
) sub0

您可以删除一些您已经拥有的子查询: -

SELECT COUNT(DISTINCT p.product_id)
FROM
(
    SELECT p.product_id
    FROM product p
    LEFT JOIN product_variant pv
      ON pv.product_variant_id = p.product_id
    LEFT JOIN depot_product_stock dps
      ON dps.product_variant_id = pv.product_variant_id
    LEFT JOIN 
    (
        SELECT pii.product_variant_id,
                SUM(IF(pii.STATUS IN ('not picked')), quantity, 0) AS pickListNotPicked_qty,
                SUM(IF(pii.STATUS IN ('picked') AND pii.date_picked > NOW() - INTERVAL 2 WEEK AND packi.picklist_id IS NULL), quantity, 0) AS pickListPicked_qty,
                SUM(IF(packi.`status` IN ('new', 'in progress')), quantity, 0) AS pickListInProgress_qty
        FROM `picklist_item` pii
        LEFT JOIN `packing` packi ON packi.picklist_id = pii.picklist_id
        GROUP BY pii.product_variant_id
    ) AS quantities
    ON quantities.product_variant_id = pv.product_variant_id
    WHERE p.deleted = 0
    GROUP BY p.product_id
    HAVING SUM(dps.physical_stock)
        - IFNULL(SUM(pickListNotPicked_qty),0)
        - IFNULL(SUM(pickListPicked_qty) ,0)
        - IFNULL(SUM(pickListInProgress_qty) ,0)
) sub0

这可以进一步简化为: -

SELECT COUNT(DISTINCT p.product_id)
FROM
(
    SELECT p.product_id
    FROM product p
    LEFT JOIN product_variant pv
      ON pv.product_variant_id = p.product_id
    LEFT JOIN depot_product_stock dps
      ON dps.product_variant_id = pv.product_variant_id
    LEFT JOIN 
    (
        SELECT pii.product_variant_id,
                SUM(quantities) AS relevant_qty
        FROM `picklist_item` pii
        LEFT JOIN `packing` packi ON packi.picklist_id = pii.picklist_id
        WHERE pii.STATUS  = 'not picked'
        OR (pii.STATUS = 'picked' AND pii.date_picked > NOW() - INTERVAL 2 WEEK AND packi.picklist_id IS NULL)
        OR packi.`status` IN ('new', 'in progress')
        GROUP BY pii.product_variant_id
    ) AS quantities
    ON quantities.product_variant_id = pv.product_variant_id
    WHERE p.deleted = 0
    GROUP BY p.product_id
    HAVING SUM(dps.physical_stock)
        - IFNULL(SUM(relevant_qty) ,0)
) sub0

请注意,如果我正确理解您的要求,我会略微不确定您的总和逻辑。您可以在上周挑选未被挑选的物品和物品。您还可以计算具有新状态或正在进行状态的项目,但看起来这些项目可能已经被计为已选择/未被选中,因此会对这些项目进行双重计算,并确保最终总和不匹配且项目为用于计算产品ID。