我想在我的股票表中实现FIFO
表格如下:
---+------------+-----------+--------+--------------+-----------
id | shift_type | item_type | amount | name | date
---+------------+-----------+--------+--------------+-----------
1 | in | apple | 50 | apple type 1 | 2017-12-01
2 | out | apple | 30 | apple type 1 | 2017-12-02
3 | in | apple | 40 | apple type 2 | 2017-12-04
4 | in | apple | 60 | apple type 3 | 2017-12-05
5 | out | apple | 20 | apple type 1 | 2017-12-07
6 | out | apple | 10 | apple type 1 | 2017-12-07
7 | in | apple | 20 | apple type 3 | 2017-12-09
并保留有关库存变化的信息。 如果我想只拿最早的收入 - 我可以记录身份最低或最早的日期。
但......也有“出局”的转变。 所以,如果我想以50个苹果为例,查询应该返回2条记录:
---+------------+-----------+--------+--------------+------------+-----
id | shift_type | item_type | amount | name | date | take
---+------------+-----------+--------+--------------+------------+-----
1 | in | apple | 50 | apple type 1 | 2017-12-01 | 20
3 | in | apple | 40 | apple type 2 | 2017-12-04 | 30
因为 - 先出(id 2)需要30个苹果,所以从收入id 1中剩余20个,其余部分应从收入ID 3中取出
如何使用SQL实现它?
答案 0 :(得分:0)
我在这里做了一些事。但需要用不同的输入进行测试。
如果没有,在外部选择查询中说50,它将为您提供需要从中获取苹果的堆栈列表。
WITH view_t
AS (
SELECT 1 id
,'in' shift_type
,'apple' item_type
,50 amount
,'apple type 1' NAME
,TO_DATE('2017-12-01', 'yyyy-mm-dd') date1
FROM dual
UNION ALL
SELECT 2
,'out'
,'apple'
,30
,'apple type 1'
,TO_DATE('2017-12-02', 'yyyy-mm-dd')
FROM dual
UNION ALL
SELECT 3
,'in'
,'apple'
,40
,'apple type 2'
,TO_DATE('2017-12-04', 'yyyy-mm-dd')
FROM dual
UNION ALL
SELECT 4
,'in'
,'apple'
,60
,'apple type 3'
,TO_DATE('2017-12-05', 'yyyy-mm-dd')
FROM dual
UNION ALL
SELECT 5
,'out'
,'apple'
,30
,'apple type 2'
,TO_DATE('2017-12-07', 'yyyy-mm-dd')
FROM dual
)
SELECT id
,date1
,shift_type
,NAME
,itemrem
,nvl((
50 - LAG(itemrem) OVER (
ORDER BY id
)
), itemrem) take
FROM (
SELECT id
,date1
,shift_type
,NAME
,SUM(amtretain) OVER (
ORDER BY id
) itemrem
FROM (
SELECT id
,date1
,shift_type
,amount
,signamt
,NAME
,CASE
WHEN LEAD(shift_type) OVER (
ORDER BY id
) = 'out'
THEN LEAD(signamt) OVER (
ORDER BY id
) + signamt
ELSE signamt
END amtretain
--date1,shift_type,sum(signamt) over(order by id)
FROM (
SELECT id
,shift_type
,NAME
,item_type
,date1
,DECODE(shift_type, 'in', amount, 'out', amount * - 1) signamt
,amount
FROM view_t
)
)
WHERE shift_type = 'in'
);
这种方法背后的想法是,