【问题标题】:Complicated Query复杂查询
【发布时间】:2013-06-28 21:37:59
【问题描述】:

我不确定是否可以仅使用 select 语句完成以下操作,但我有两个表(截断了问题所需的数据)。

库存项目

  • id int(主要)
  • 数量int

Stock - 包含库存项目的库存变化(库存历史)

  • id int(主要)
  • inventory_item_id int(外键)
  • 数量int
  • 创建日期时间

库存中的数量是库存的变化,而库存项目中的数量是该项目的当前数量

running 列中的所有内容都将返回 0

SELECT
inventory_item.id,
(inventory_item.quantity - SUM(stock.quantity)) AS running
FROM
    stock
        JOIN
    inventory_item ON stock.inventory_item_id = inventory_item.id
GROUP BY inventory_item.id

问题

现在,我想知道的是:是否可以使用 SELECT 选择库存表中库存项目的运行数量变为零的所有日期?

我知道这可以通过简单地选择一个项目中的所有库存数据并从当前库存项目数量中单独减去库存数量来以编程方式完成,这将获得库存变化发生之前的数量。我可以使用 SELECT 执行此操作吗?

【问题讨论】:

  • 对于给定的inventory_item_id 和created 组合是否会有多个记录?

标签: mysql


【解决方案1】:

(已更新)假设给定的 inventory_item_id 和 created 组合永远不会超过一条记录,请尝试:

SELECT i.id,
       s.created,
       i.quantity - COALESCE(SUM(s2.quantity),0) AS running
FROM inventory_item i
JOIN stock s ON s.inventory_item_id = i.id
LEFT JOIN stock s2 ON s2.inventory_item_id = i.id and s.created < s2.created
GROUP BY i.id, s.created
HAVING running=0

【讨论】:

  • 由于 i.quantity 是最新的数量,这是不正确的。我认为您需要将running 字段更改为SUM(s2.quantity)。然后这将返回所有库存日期的正确结果,而不仅仅是最新的。
  • @Tom:我已经修改了查询以考虑您提出的观点。单独使用stock.quantity 的总和作为总和是不正确的,因为它用于保存库存数量的变化 - 求和会告诉我们发生了多少变化,但不是当时的库存水平。
  • 我假设 stock.quantity 的总和是运行总数,因为他说:“库存数量是库存的变化,而库存项目的数量是该项目的当前数量正在运行的列中的所有内容都将返回 0"。也许我解释错了?我认为 stock 表中的第一个条目将是期初库存。
  • 如果有或没有完整的股票历史记录,您拥有它的方式会起作用。因此,除非您知道自己拥有完整的股票历史记录,否则这可能是最安全的方式。
【解决方案2】:

我相信这是一个简单的方法。

SELECT inventory_item.id, stock.created

FROM   inventory_item

       JOIN stock ON stock.inventory_item_id = inventory_item.id

WHERE  (SELECT SUM(quantity) FROM stock WHERE created <= stock.created) = 0

【讨论】:

    【解决方案3】:

    我有一个类似的响应,基于要标记的运行总数found here...

    您可以使用 MySQL @variables,但数据需要预先查询并按活动数据排序......然后在每行上设置一个导致负数的标志并只保留那些。类似的东西

    select 
          PreQuery.*
       from 
          ( select
                  s.id,
                  s.created,
                  @runBal := if( s.id = @lastID, @runBal - quantity, @i.quantity ) as CurBal,
                  @lastID := s.id as IDToCompareNextEntry
               from
                  stock s
                     join inventory_item ii
                        on s.inventory_item_id = ii.id,
                  (select @lastID := -1,
                          @runBal := 0 ) sqlvars
               order by
                  s.id,
                  s.created DESC ) PreQuery
       where
          PreQuery.CurBal < 0
    

    这样,对于每个库存项目,它按创建日期向后工作(按创建的每个 ID 降序排列)。因此,当库存 ID 发生变化时,请查看库存表的“数量”字段以开始统计已用库存。如果与处理的最后一条记录相同的 ID,则只需使用流转余额并减去该库存条目的数量。

    【讨论】:

      【解决方案4】:

      我的看法:

      select
          inventory_item_id `item`,
          created `when`
      from
          (select 
               @total := CASE WHEN @curr <> inventory_item_id
                         THEN quantity
                         ELSE @total+quantity END as running_total,
               inventory_item_id,
               created,                   
               @curr := inventory_item_id
           from
               (select @total := 0) a
               (select @curr  := -1) b
               (select inventory_item_id, created, quantity from stock order by inventory_item_id, created asc) c
           ) running_total
      where running_total.running_total = 0;
      

      这个相对的优势是只需要给股票表一次通行证。取决于大小和它上面的索引,这可能是一件好事,也可能不是一件好事。

      【讨论】:

        【解决方案5】:

        最合乎逻辑的方法是使用累积和。但是,MySQL 不支持。

        在我看来,最清晰的方法是使用相关子查询来获取运行量。然后就是一个简单的where子句来选择0的位置:

        select i.*
        from (select i.*,
                     (select SUM(i2.inventory)
                      from inventory i2
                      where i2.inventory_item_id = i.inventory_item_id and
                            i2.created <= i.created
                     ) as RunningQuantity
              from inventory i
             ) i
         where RunningQuantity = 0;
        

        【讨论】:

          猜你喜欢
          • 2017-05-10
          • 2014-11-06
          • 2011-06-08
          • 2012-10-25
          • 2017-05-22
          • 2012-02-02
          • 2023-04-08
          • 2012-08-18
          • 1970-01-01
          相关资源
          最近更新 更多