【问题标题】:Subqueries problem (look for the highest date before X date)子查询问题(查找 X 日期之前的最高日期)
【发布时间】:2021-03-29 12:43:28
【问题描述】:

我想计算公司在某些给定日期的股票。由于我们没有股票表,我需要根据股票走势来计算它。 ENTRAN = 添加和SALEN = 减去,从该日期之前的最后一个库存开始。

我必须检查的日期是销售前库存变动的最后几天。

我想使用连接到移动库存表的销售表。

股票走势表 (MOVSTOCKS) 如下所示:

SKU     entran     salen     codalm     fecdoc         tipdoc    
ART1      50        10          2       01-03-2021      IN
ART1      100                   2       03-03-2021      AC
ART1                30          2       05-03-2021      AV
ART2      100       50          2       01-03-2021      IN
ART2                50          2       02-03-2021      AV
ART2      30        50          2       03-03-2021      IN 
ART2                20          2       03-03-2021      AV
ART2      50                    2       04-03-2021      AC
ART2                30          2       05-03-2021      AV

每个IN 都是一个库存。当有库存时,我必须取ENTRAN 的值,并从那里继续计算,增加或减少单位。

AC 是购买,AV 是销售。

因此,销售表 (LINEALBA) 应显示此数据以及其他列:

Date          SKU      QTY      Cumulative
05-03-2021    ART1     30          150
02-03-2021    ART2     50          100
03-03-2021    ART2     20          30
05-03-2021    ART2     30          60

每一行都是一次销售 (AV),cumulative 列查看该销售之前的最后一个库存 01-03-202103-03-2021,它会添加和减去数量,并显示计算出的库存销售前一天。

这是我的查询(不工作):

select  *
from    (select     m*,
                    LastInventory + sum(m.entran - m.salen) 
                       over (partition by m.codart order by m.fecdoc) as cumulative,
                    max(m.fecdoc) over (partition by m.codart) as max_fecdoc,
                    m.fecdoc
        from        MovStocks m
        left join   LINEALBA l on l.codart = m.codart
        left join   (select     m2.codart as SKU,
                                m2.entran as LastInventory,
                                max(m2.fecdoc) over (partition by m2.codart, m2.tipdoc) as LastDateinventory,
                                m2.fecdoc
                    from        MovStocks m2
                    where       m2.codalm in (2)
                    and         m2.tipdoc = 'IN') m2
            on      m2.CODART = m.codart
        where       m.codalm in (2)
        and         m2.fecdoc = LastDateinventory
        and         m.fecdoc < v.fecha
        and         m.fecdoc > LastDateinventory
        and         LastDateinventory < v.fecha
        and         m.tipdoc <> 'IN') m
        where       max_fecdoc = m.fecdoc

我的想法是创建一个子查询,或 CTE,Idk,它查看销售前的最后一个库存是什么时候,查看销售前的最后一个动作是什么时候,然后以库存为基础计算库存(就像它是 0 一样)。

由于某种原因,我的查询未正确计算此累积值。不知道是过滤器的问题还是我的子查询不正确...

任何帮助将不胜感激。非常感谢。

【问题讨论】:

  • 你为什么在这里使用GROUP BY?您的内部或外部查询中没有相关的聚合。
  • @Larnu 由于entransalen,我有一些重复的行,但是如果不按这两列对内部查询进行分组,我就无法显示数据。所以我将内部查询与entran 和salen 分组,而外部查询没有它们。
  • 这通常意味着您的JOIN(更具体地说是您的ON)子句是错误的。在没有聚合的每一列上执行GROUP BY 是毫无意义且令人困惑的;您最好(如果必须)使用DISTINCT,但是,我更确定问题是您的JOINs 存在某种多对一/多关系导致“重复”(它们不会是真的相同,所以不是真正的重复)行。那,或者您不应该在内部查询中使用窗口聚合,并且应该完全删除外部 GROUP BY
  • 好的,我删除了内部和外部分组。使用DISTINCT 我得到相同数量的行。那挺好的。现在的问题是累积的。我不知道如何正确计算它,我不知道我的子查询是否正确或过滤器是否有问题:and m2.fecdoc = LastDateinventoryand m.fecdoc &lt; v.fechaand m.fecdoc &gt; LastDateinventoryand LastDateinventory &lt; v.fecha、@ 987654351@
  • 将您的问题编辑为Minimal reproducible example,使您的查询简洁明了,以说明您要解决的问题,以及示例数据和预期结果。

标签: sql-server subquery correlated-subquery


【解决方案1】:

分而治之!

-- Add sequence number with SKU.
-- Rows may be uniquely identify by SKU & seq number.
With Qry1 As (
    SELECT      SKU,
                entran,
                salen,
                codalm,
                fecdoc,
                tipdoc,
                ROW_NUMBER() OVER(Partition By SKU Order By fecdoc) As Seq
    FROM        MOVSTOCKS
),

-- Get seq # of most recent inventory for each SKU.
Qry2 As (
    SELECT      qry11.sku,
                qry11.seq,
                max(qry12.seq) as prev_inv_seq
    FROM        Qry1 qry11
    inner join  Qry1 qry12
    on          qry11.sku = qry12.sku
    and         qry11.fecdoc >= qry12.fecdoc
    where       qry12.tipdoc = 'IN'
    group by    qry11.sku,
                qry11.seq
), 

-- Get quantity of most recent inventory for each SKU.
Qry3 As (
    SELECT      qry2.sku,
                qry2.seq,
                qry1.entran as prev_inv_entran
    FROM        Qry2 
    inner join  Qry1
    on          qry2.sku = qry1.sku
    and         qry2.prev_inv_seq = qry1.seq
), 

-- Get sum of purchase quantities since most recent inventory for each SKU.
Qry4 As (
    SELECT      qry2.sku,
                qry2.seq,
                sum(qry1.entran) as sum_entran
    FROM        Qry2 
    inner join  Qry1 qry1
    on          qry2.sku = qry1.sku
    where       qry1.seq > qry2.prev_inv_seq
    and         qry1.seq < qry2.seq
    AND         qry1.tipdoc = 'AC'
    group by    qry2.sku,
                qry2.seq
), 

-- Get sum of sales quantities since most recent inventory for each SKU.
Qry5 As (
    SELECT      qry2.sku,
                qry2.seq,
                sum(qry1.salen) as sum_salen
    FROM        Qry2 
    inner join  Qry1 qry1
    on          qry2.sku = qry1.sku
    where       qry1.seq > qry2.prev_inv_seq
    and         qry1.seq < qry2.seq
    AND         qry1.tipdoc = 'AV'
    group by    qry2.sku,
                qry2.seq
)

-- Pull it all together...
SELECT      qry1.fecdoc As Date,
            qry1.SKU,
            qry1.salen As Quantity,
            qry3.prev_inv_entran + IsNull(qry4.sum_entran, 0) - IsNull(qry5.sum_salen, 0) as Cumulative
FROM        qry1
left JOIN   Qry3
on          qry3.sku = qry1.sku
and         qry3.seq = qry1.seq
left JOIN   Qry4
on          qry4.sku = qry1.sku
and         qry4.seq = qry1.seq
left JOIN   Qry5
on          qry5.sku = qry1.sku
and         qry5.seq = qry1.seq
WHERE       qry1.tipdoc = 'AV'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 2019-03-21
    • 1970-01-01
    • 2014-12-06
    • 2011-08-22
    相关资源
    最近更新 更多