如何使用mysql子查询减去库存和销售?

时间:2015-02-10 16:17:29

标签: mysql sql database subquery

尝试了解有关子查询的更多信息。我正在寻找一种方法来减去和比较两个表。

  1. 广告
  2. 销售
  3. 我的数据记录如下:

    广告:

    mysql> select store_id, product_id, sum(quantity) as inventory from inventories where store_id = 1 group by product_id;
    +----------+------------+-----------+
    | store_id | product_id | inventory |
    +----------+------------+-----------+
    |        1 |          8 |        24 |
    |        1 |         10 |         4 |
    |        1 |         14 |        24 |
    +----------+------------+-----------+
    3 rows in set (0.00 sec)
    

    销售

    mysql> select store_id, product_id, sum(quantity) as sales from sales where store_id = 1 group by product_id;
    +----------+------------+-------+
    | store_id | product_id | sales |
    +----------+------------+-------+
    |        1 |          8 |    12 |
    |        1 |         14 |     2 |
    |        1 |          8 |     1 |
    +----------+------------+-------+
    2 rows in set (0.00 sec)
    

    具有以下结果的正确子查询是什么?

    +----------+------------+-----------+-------+-----------+
    | store_id | product_id | inventory | sales | remaining |
    +----------+------------+-----------+-------+-----------+
    |        1 |          8 |        24 |    12 |        12 |
    |        1 |         14 |        24 |     2 |        22 |
    |        1 |          8 |        12 |     1 |        11 |
    +----------+------------+-----------+-------+-----------+
    

7 个答案:

答案 0 :(得分:3)

要获得所需的输出,您需要计算产品销售的总计。要获得有意义的数据,sales表中的数据必须按时间顺序排序。因此,您至少需要一个字段来对数据进行排序 - 无论是时间戳还是id字段都无关紧要。假设销售表中有id字段。这是一个获得您所描述内容的查询:

SELECT 
    sales.id,
    sales.store_id,
    sales.product_id,
    inventories.quantity-IFNULL(SUM(sales_2.quantity), 0) as inventory,
    sales.quantity as sales,
    inventories.quantity-IFNULL(SUM(sales_2.quantity), 0) - sales.quantity as remaining
FROM
    sales
        INNER JOIN
    inventories ON inventories.store_id = sales.store_id
        AND inventories.product_id = sales.product_id
        LEFT JOIN
    sales AS sales_2 ON sales_2.store_id = sales.store_id
        AND sales_2.product_id = sales.product_id
        AND sales_2.id < sales.id
GROUP BY sales.id , sales.store_id , sales.product_id
ORDER BY sales.id

名为sales的{​​{1}}表的第二个实例用于计算早期销售额的总和(sales_2

您可以从sales_2.id<sales.id子句中排除sales.id,但您需要将其保留在selectgroup by中。

答案 1 :(得分:3)

您可以使用查询中的结果并加入它们来计算每种产品的剩余数量

SELECT 
a.store_id,
a.product_id,
a.inventory,
b.sales,
a.inventory - b.sales AS remaining
FROM (
SELECT store_id, product_id, COALESCE(SUM(quantity),0) AS inventory 
FROM inventories WHERE store_id = 1 
GROUP BY product_id) a
LEFT JOIN (
SELECT store_id, product_id, COALESCE(SUM(quantity),0) AS sales
 FROM sales WHERE store_id = 1 
 GROUP BY product_id ) b USING(store_id, product_id)

答案 2 :(得分:2)

尝试将两个表连接为:

SELECT I.store_id, I.product_id, I.inventory, S.sales, (I.inventory - S.sales) AS remaining
FROM Sales S INNER JOIN INVENTOR I
ON I.store_id = S.store_id
AND I.product_id = S.product_id

答案 3 :(得分:1)

我发布了一个答案,然后重新阅读了你想要的内容。我意识到我读错了东西,我发现你确实希望将销售视为按顺序扣除的个别交易,即&#34;历史&#34;。您仍然需要某种交易ID或交易日期来确定它们应用于哪个订单。在另一个答案中也已经注明了这一点。也许你想依赖MySQL行id或其他东西。我对MySQL没有足够的了解,可以帮助你解决这个问题。

select
    i.store_id, i.product_id,
    i.inventory - s.previous_sales as inventory,
    s.quantity as sales,
    i.inventory - s.previous_sales - s.quantity as remaining
from
    inventories as i inner join
    (
    select store_id, product_id, quantity,
        (
        select sum(quantity)
        from sales as s2
        where
            s2.store_id = s.store_id and s2.product_id = s.product_id
            /* all sales for this store and product prior to this one */
            and s2.[sequencing column] < s.[sequencing column]
        ) as previous_sales
    from sales
    group by store_id, product_id
    ) as s
        on s.store_id = i.store_id and s.product_id = i.product_id
where
    i.store_id = 1

我不知道您将如何处理广告资源中的更改或者需要从广告资源中扣除的销售回溯量。这可以在您编写时解决问题。

答案 4 :(得分:1)

样本数据非常有限,但我相信我们可以做出这些假设。

  1. 除非已将商品记录为库存,否则您无法销售商品
  2. 您可以拥有尚未售出的库存商品
  3. 如果没有必要聚合库存,那么您可以使用单个&#34;派生表&#34;,这是一种子查询,如下所示:

        SELECT
              I.store_id
            , I.product_id
            , COALESCE(I.inventory, 0) AS INVENTORY
            , COALESCE(S.sales, 0) AS SALES
            , COALESCE(I.inventory, 0) - COALESCE(S.sales, 0) AS REMAINING
        FROM Inventory I
        LEFT JOIN (
              SELECT
                    store_id
                  , product_id
                  , SUM(sales) AS SALES
              FROM Sales
              WHERE store_id = 1
              GROUP BY
                    product_id
        ) S ON I.store_id = S.store_id
                    AND I.product_id = S.product_id
        WHERE I.store_id = 1
        ORDER BY
              I.store_id
            , I.product_id
        ;
    

    如果还需要汇总库存,您可以使用2&#34;派生表&#34;像这样:

    SELECT
          I.store_id
        , I.product_id
        , COALESCE(I.inventory, 0) AS INVENTORY
        , COALESCE(S.sales, 0) AS SALES
        , COALESCE(I.inventory, 0) - COALESCE(S.sales, 0) AS REMAINING
    FROM (
          SELECT
                store_id
              , product_id
              , SUM(inventory) AS INVENTORY
          FROM Inventory
          WHERE store_id = 1
          GROUP BY
                product_id
    ) I
    LEFT JOIN (
          SELECT
                store_id
              , product_id
              , SUM(sales) AS SALES
          FROM Sales
          WHERE store_id = 1
          GROUP BY
                product_id
    ) S ON I.store_id = S.store_id
                AND I.product_id = S.product_id
    ORDER BY
          I.store_id
        , I.product_id
    ;
    

    或者您可以使用&#34;相关子查询&#34;在select子句中,如下所示:

    SELECT
          I.store_id
        , I.product_id
        , COALESCE((
                SELECT
                      SUM(sales)
                FROM sales S
                WHERE S.store_id = I.store_id
                      AND S.product_id = I.product_id
          ), 0) AS SALES
        , I.inventory - COALESCE((
                SELECT
                      SUM(sales)
                FROM sales S
                WHERE S.store_id = I.store_id
                      AND S.product_id = I.product_id
          ), 0) AS REMAINING
    FROM Inventory AS I
    WHERE I.store_id = 1
    ORDER BY
          I.store_id
        , I.product_id
    ;
    

    您已经问过哪个是&#34;正确的子查询&#34;。我相信以上所有语法都是正确的,但是&#34;正确的&#34;我不完全明白。如果你的意思是哪个会表现最好,我会建议派生表优先于相关子查询,但要得出适用于所有情况的答案几乎是不可能的。

    要评估最佳性能需要更好地定义数据,表和索引,强烈建议使用执行计划。也可能是不使用任何子查询是最好的方法(即连接)。

    在此处查看上述查询作为示例:http://sqlfiddle.com/#!9/fa6b6/1

答案 5 :(得分:1)

理想的子查询将是使用表格键的子查询。

对于您的库存表,您应该有一个PRIMARY KEY(store_id,product_id)。

ALTER TABLE inventories ADD PRIMARY KEY (store_id, product_id).

如果这不是唯一的(在这种情况下,它实际上不是库存,而是“传入项目”表),您可以为这两列设置INDEX。

ALTER TABLE inventories ADD INDEX (store_id, product_id).

您必须在销售表中定义相同的索引

ALTER TABLE sales ADD INDEX (store_id, product_id).

在定义这些键之后,我们可以知道设置完美和长效的子查询。

  1. 第一个假设:您在库存中为(store_id,product_id)定义了主键
  2. SQL:

     SELECT t1.store_id, t1.product_id, t1.quantity inventory,
           IFNULL(sum(t2.quantity), 0) sales,
           t1.quantity-IFNULL(sum(t2.quantity), 0) remaining
         FROM inventories t1
             LEFT JOIN sales t2 ON t1.store_id=t2.store_id
             AND t1.product_id=t2.product_id
          WHERE t1.store_id=1
          GROUP BY t1.store_id, t1.product_id;
    
    1. 第二个假设:只是一个指数,事情变得更复杂
    2. 除了查询inventories表而不是查询SELECT store_id, product_id, SUM(quantity) quantity FROM inventory GROUP BY store_id, product_id; 表之外,你做了同样的事情,你将用以下子查询替换它:

       SELECT t1.store_id, t1.product_id, t1.quantity inventory,
             IFNULL(sum(t2.quantity), 0) sales,
             t1.quantity-IFNULL(sum(t2.quantity), 0) remaining
           FROM 
              (SELECT store_id, product_id, SUM(quantity) quantity
                 FROM inventory
                 GROUP BY store_id, product_id) t1
             LEFT JOIN sales t2 ON t1.store_id=t2.store_id
             AND t1.product_id=t2.product_id
           WHERE t1.store_id=1
           GROUP BY t1.store_id, t1.product_id;
      

      结果将如下:

      {{1}}

答案 6 :(得分:1)

假设您有一个产品表和一个商店表,然后将它们加在一起,以获得产品和商店的组合。这样,一行不依赖于您感兴趣的商店中仍在库存中的产品,或者尚未从您感兴趣的商店销售的产品。

然后LEFT OUTER JOIN子查询以获取库存和销售或每个产品/商店。

SELECT b.store_id, a.product_id, IFNULL(c.inventory, 0), IFNULL(d.sales, 0) , (IFNULL(c.inventory, 0) - IFNULL(d.sales, 0)) AS remaining
FROM products a
INNER JOIN stores b
ON b.store_id = 1
LEFT OUTER JOIN 
(
    SELECT store_id, product_id, SUM(quantity) AS inventory 
    FROM inventories 
    WHERE store_id = 1 
    GROUP BY store_id, product_id
) c
ON a.product_id = c.product_id
AND b.store_id = c.store_id 
LEFT OUTER JOIN 
(
    SELECT store_id, product_id, SUM(quantity) AS sales 
    FROM sales 
    WHERE store_id = 1 
    GROUP BY store_id, product_id
) d
ON a.product_id = d.product_id
AND b.store_id = d.store_id