我们当前的计算缺货的方法不再适用于我们如何跟踪库存以及如何查看数据。我要使用的新方法是只查看过去一年中每一天的最终OnHandAfter值。我们不是24/7,因此每天结束时输入的最后一个值将告诉我们该商品当天是否缺货。 如果某商品在某个日期没有库存交易,则应使用上次找到的日期。
ABDailyCalendar abdc
这是表格,其中预填了过去一年中的每个日期
库存数据样本(如果cte单独运行,那么cte会返回单个项目的内容,为简便起见,我省略了一些列)
ItemCode TransactionDate OnHandAfter rn
Item-123 10/1/2018 960 1
Item-123 9/28/2018 985 1
Item-123 9/27/2018 1085 1
Item-123 9/26/2018 1485 1
Item-123 9/24/2018 1835 1
Item-123 9/20/2018 2035 1
Item-123 9/18/2018 2185 1
Item-123 9/14/2018 2305 1
Item-123 9/13/2018 2605 1
我的查询
with cte as
(
Select TOP 1 * from
(
Select
ItemCode
,convert(Date,TransactionDate) TransactionDate
,TransactionType
,TransactionQuantity
,OnHandBefore
,OnHandAfter
,ROW_NUMBER() over (partition by ItemCode, CONVERT(Date, TransactionDate) order by TransactionDate DESC) as rn
from InventoryTransaction
where TransactionType in (1,2,4,8)
) as ss
where rn = 1
order by TransactionDate DESC
)
SELECT
ab.ExternalId
,abdc.[Date]
,cte.TransactionDate
From ABItems ab CROSS JOIN ABDailyCalendar abdc
FULL OUTER JOIN cte on cte.ItemCode = ab.ExternalId --and cte.TransactionDate <= abdc.[Date]
Where ab.ExternalID = 'Item-123'
order by abdc.[Date] DESC
当前样品结果
ExternalId Date TransactionDate
Item-123 9/30/2018 NULL
Item-123 9/29/2018 NULL
Item-123 9/28/2018 NULL
Item-123 9/27/2018 NULL
Item-123 9/26/2018 NULL
Item-123 9/25/2018 NULL
Item-123 9/24/2018 NULL
所需结果
ExternalId Date TransactionDate
Item-123 9/30/2018 9/28/2018
Item-123 9/29/2018 9/28/2018
Item-123 9/28/2018 9/28/2018
Item-123 9/27/2018 9/27/2018
Item-123 9/26/2018 9/26/2018
Item-123 9/25/2018 9/24/2018
Item-123 9/24/2018 9/24/2018
TransactionDate
应该是最新的TransactionDate
,它是{=到Date
的地方。
如果有关系-我正在运行连接到SQL Server 2008的SSMS 2012。
任何指针或想法将不胜感激。我盯着它看了很久,以至于没有新的东西出现。谢谢。
答案 0 :(得分:0)
我使用了postgres,但此操作与SQLS大致相同。这是我在评论中所写内容的暗示:
https://www.db-fiddle.com/f/uKcgh9yZVvvqfRWTERv2a3/0
我们在小提琴的左侧制作了一些样本数据。这是特定于PG的,但不要太在意-最终结果是它到达的位置与SQLS中的数据相同
然后查询:
SELECT
itemcode,
caldate,
case when caldate = transactiondate then onhandafter else prev_onhandafter end as onhandat,
case when caldate = transactiondate then 'tran occurred today, using current onhandafter' else 'no tran today, using previous onhandafter' end as reasoning,
transactiondate,
onhandafter,
prev_onhandafter
FROM
(
SELECT
itemcode,
transactiondate,
LAG(transactiondate) over(partition by itemcode order by transactiondate) as prev_transactiondate,
onhandafter,
LAG(onhandafter) over(partition by itemcode order by transactiondate) as prev_onhandafter
FROM
t
) t2
INNER JOIN
c
ON
c.caldate > t2.prev_transactiondate and c.caldate <= t2.transactiondate
ORDER BY itemcode, caldate
itemcode / externalid(两者都被称为
)一堆日期-您的日期是DATE还是DATETIME,它们是可比较的。如果需要,将DATETIME强制转换为DATE并没有什么害处,并且如果您的任何日期包含时间分量,则这样做很重要,因为2018-01-01 00 :00不是与2018年1月1日 01 :00相同,并且如果您的日历表具有午夜,并且transactiondate是凌晨1点,则范围联接条件(caldate > prevtrandate and caldate <= trandate
)将不起作用正确地出来。随意将其作为联接的一部分进行转换:caldate > CAST(prevtrandate as DATE) and caldate <= CAST(trandate as DATE)
。如果可以确保您的日期时间100%准确地在午夜(微秒),那么连接将成功进行而无需强制转换-此处的强制转换是缩短时间并确保苹果与苹果进行比较的快速技巧
好的,这是如何工作的:
我没有使用cte对表中的行进行编号并将其自身连接在一起,而是使用了类似的技术,使用LAG来获取我感兴趣的上一行的值。上一章被定义为“按项目代码递增转换顺序”。这为我们提供了具有当前日期,前一个日期的行(注意:第一行为null,如果需要的话,则需要一些额外的查询,例如COALESCE(lag(...),trandate))保留下来,否则加入后就会消失。我们将使用日期对加入,稍后我们将选择显示当前的还是先前的。
此操作作为子查询完成,因此可以使用上一个值。它在日历日期大于上一个日期且小于或等于当前日期的日期加入日历表。这意味着笛卡尔乘积会填补交易日期中的所有空白,因此我们可以从日历表中获得一组连续的日期。
我们使用一种情况来检查数据-如果校准日期等于转换日期,我们将使用新值作为现值,因为今天发生了转换并减少了库存。否则,我们可以断言今天没有交易,而应该使用prev on hand。
希望这对于您想要的东西来说是正确的(您似乎表明这是您真正想要的事,但是您想要的查询输出只提到了交易日期/日期对
编辑:好的,延迟不可用-这是一个使用行号的解决方案:
https://www.db-fiddle.com/f/2ooVrNF18stUQAa4HyTj6r/0
WITH cte AS(
SELECT
itemcode,
transactiondate,
ROW_NUMBER() over(partition by itemcode order by transactiondate) as rown,
onhandafter
FROM
t
)
SELECT
curr.itemcode,
c.caldate,
case when c.caldate = curr.transactiondate then curr.onhandafter else prev.onhandafter end as onhandat,
case when c.caldate = curr.transactiondate then 'tran occurred today, using current onhandafter' else 'no tran today, using previous onhandafter' end as reasoning,
curr.transactiondate,
curr.onhandafter,
prev.onhandafter
FROM
cte curr
INNER JOIN
cte prev
ON curr.rown = prev.rown + 1 and curr.itemcode = prev.itemcode
INNER JOIN
c
ON
c.caldate > prev.transactiondate and c.caldate <= curr.transactiondate
ORDER BY curr.itemcode, c.caldate
工作原理:与我的第一句话差不多。我们按转换日期的顺序将表分为项目代码和行号。我们将此操作作为CTE,因此from cte curr inner join cte prev on curr.rownumber = prev.rownumber+1
滞后-我们有一排包含当前值和先前值的行。其余查询逻辑从上方保持不变