Forcast履行sql查询

时间:2016-12-27 11:53:35

标签: sql oracle

我遇到了一个要求,我需要编写sql查询,根据仓库等级和销售排名将库存从一个位置填充到另一个位置。 以下是场景: 我有一张桌子有剩余数量的产品A(表1) 我有另一张表,其中包含产品A的所需数量(预测)(表2)。

我需要将产品数量从(表1)A发送到(表2)B,根据它们的等级(对于A SOH_RNK,对于B SLS_RNK)

表1:

PROD_ID SOH_RNK QTY STORE_ID_A
A           1   30  30105
A           2   16  21168
A           3   10  21032
A           4   9   30118
A           9   6   30011
A           10  5   21190
A           13  2   21016

表2:

PROD_ID SLS_RNK Forcast_QTY STORE_ID_B
A           1       15      21005
A           2       10      30019
A           3       11      21006
A           4       16      30001
A           5       11      21015
A           6       7       21004

预期输出:

Store_ID_B  Store_id_A  Transferred_Qty_from_A
21005           30105           15
30019           30105           10
21006           30105           5
21006           21168           6
30001           30105           0
30001           21168           10
30001           21032           6
21015           30105           0
21015           21168           0
21015           21032           4
21015           30118           7
21004           30105           0
21004           21168           0
21004           21032           0
21004           30118           2
21004           30011           5

到目前为止,我已尝试过制作交叉连接,但没有多大帮助。我试图避免程序方法,因为它将逐行,我有2000万这样的记录。

1 个答案:

答案 0 :(得分:1)

这个想法是确定两个表中的数量范围,然后根据这些范围连接两个表,以获得从源存储发送到目标存储的产品数量。

这是计算第一个表的范围的查询示例(第二个表的查询类似于此表):

  select t1.*,
         coalesce(sum( qty ) 
             over ( order by soh_rnk 
                   range between unbounded preceding and 1 preceding),
             0) As range_start,
         sum( qty ) over ( order by soh_rnk ) As range_end
  from table1 t1

PROD_ID |SOH_RNK |QTY |STORE_ID_A |RANGE_START |RANGE_END |
--------|--------|----|-----------|------------|----------|
A       |1       |30  |30105      |0           |30        |
A       |2       |16  |21168      |30          |46        |
A       |3       |10  |21032      |46          |56        |
A       |4       |9   |30118      |56          |65        |
A       |9       |6   |30011      |65          |71        |
A       |10      |5   |21190      |71          |76        |
A       |13      |2   |21016      |76          |78        |

现在,当两个表中的两个数据范围相互重叠时,我们可以连接两个表中的记录 可以在此处找到用于检查两个范围是否重叠的公式:http://www.soliantconsulting.com/blog/2016/03/determining-if-two-date-ranges-overlap

它是:NOT (EndA <= StartB or StartA >= EndB)

最后的查询:

WITH  t1 AS (
  select t1.*,
         coalesce(sum( qty ) over ( order by soh_rnk range between unbounded preceding and 1 preceding),0) As range_start,
         sum( qty ) over ( order by soh_rnk ) As range_end
  from table1 t1
),
t2 As (
    select t2.*,
           coalesce(sum( forecast_qty ) over ( order by sls_rnk range between unbounded preceding and 1 preceding),0) As range_start,
           sum( forecast_qty ) over ( order by sls_rnk ) As range_end
    from table2 t2
)
SELECT 
       t1.store_id_a,
       t2.store_id_b,
       least( t1.range_end, t2.range_end ) - greatest( t1.range_start, t2.range_start ) As Transferred_Qty_from_A
FROM t1
join t2
-- NOT (EndA <= StartB or StartA >= EndB)
on not ( t1.range_end <= t2.range_start OR t1.range_start >= t2.range_end)
   and t1.prod_id = t2.prod_id
order by soh_rnk, sls_rnk
;

此查询的结果是:

STORE_ID_A |STORE_ID_B |TRANSFERRED_QTY_FROM_A |
-----------|-----------|-----------------------|
30105      |21005      |15                     |
30105      |30019      |10                     |
30105      |21006      |5                      |
21168      |21006      |6                      |
21168      |30001      |10                     |
21032      |30001      |6                      |
21032      |21015      |4                      |
30118      |21015      |7                      |
30118      |21004      |2                      |
30011      |21004      |5                      |

不幸的是,我不知道如何在结果集中包含0数量的记录(当没有产品从第1个商店转移到第2个商店时)。