sql server 2008中的SQL FIFO逻辑

时间:2016-05-30 13:04:04

标签: sql sql-server fifo

如果这个标题不代表我的问题,我很抱歉。

我的表1有多个项目。

表1

|No|Item|Quantity X|    
|1 |A   |20        |
|2 |A   |21        |
|3 |A   |10        |
|4 |B   |3         |
|5 |B   |4         |
...

我对项目A的自定义FIFO功能结果:

|No|Name     |Quantity Y|           
|1 |Document1|2         |   
|2 |Document2|20        |   
|3 |Document3|5         |   
|4 |Document4|1         |   
|5 |Document5|22        |           

我的项目B的自定义FIFO功能结果:

|No|Name       |Quantity Y|         
|1 |Document100|2         | 
|2 |Document101|2         | 
|3 |Document102|4         | 

预期结果:

表2

Item|Quantity X|Name       |Quantity Y|
A   |20        |Document1  |2         |
A   |20        |Document2  |18        |
A   |21        |Document2  |2         |
A   |21        |Document3  |5         |
A   |21        |Document4  |1         |
A   |21        |Document5  |13        |
A   |10        |Document5  |10        |
B   |3         |Document101|2         |
B   |3         |Document102|1         |
B   |4         |Document102|1         |
B   |4         |Document103|3         |

我使用的是SQL Server 2008.如何使用SQL实现这一目标?

1 个答案:

答案 0 :(得分:1)

我在这里得到一个奇怪的答案:)请坐下看看。

--I use cte's to show you a sample of how it wiil work
--Here comes table with incoming docs
;WITH table1 as (
SELECT * 
FROM (VALUES
(1, 'A',  20),(2, 'A',  21),(3, 'A',  10),(4, 'B',  3),(5, 'B',  4)
)AS t([No],Item,[Quantity X])
--Here comes table with outgoing item A
), itemA AS (
SELECT * 
FROM (VALUES        
(1, 'Document1',2),(2, 'Document2',20),(3, 'Document3',5),(4, 'Document4',1),(5, 'Document5',22)
)AS t([No], Name, [Quantity Y])   
--Here we fraction each quantity for documents in 1, 
--so if quantity is 20 there will be 20 rows with 1 
), recT1 AS (
    SELECT [No], Item, [Quantity X], 1 as [level], 1 as Qty
    FROM table1
    WHERE Item = 'A'
    UNION ALL
    SELECT [No], Item, [Quantity X], [level] +1,1
    FROM recT1 
    WHERE [level] < [Quantity X]
--same to items
), recA AS (
    SELECT [No], [Quantity Y], 1 as [level], 1 as Qty
    FROM itemA
    UNION ALL
    SELECT [No], [Quantity Y], [level] +1,1
    FROM recA 
    WHERE [level] < [Quantity Y]
--here we add ROW_NUMBER not to lost order
), finalT1 as (
    SELECT *, ROW_NUMBER() OVER (ORDER BY [No], [Level]) as rn
    from recT1 
), finalA as (
    SELECT *, ROW_NUMBER() OVER (ORDER BY [No], [Level]) as rn
    FROM recA
)
--final query!
SELECT  t.Item,
        t.[Quantity X],
        ia.Name,
        CASE WHEN a.[level] > t.[level] THEN t.[level] ELSE a.[level] END as [Quantity Y]
FROM finalT1 t
INNER JOIN finalA a
    ON t.rn = a.rn
LEFT JOIN itemA ia
    ON ia.[No] = a.[No]
WHERE a.[level] = a.[Quantity Y] or t.[level] = t.[Quantity X] 

输出:

Item    Quantity X  Name        Quantity Y
A       20          Document1   2
A       20          Document2   18
A       21          Document2   2
A       21          Document3   5
A       21          Document4   1
A       21          Document5   13
A       10          Document5   9

B

Item    Quantity X  Name        Quantity Y
B       3           Document100 2
B       3           Document101 1
B       4           Document101 1
B       4           Document102 3