从范围表中选择范围

时间:2019-03-29 04:29:29

标签: sql sql-server

我有2个范围表ReceivedRangesDispatchedRanges

ReceivedRanges
 From  - To
     1 - 100000
200000 - 300000
350000 - 400000


DispatchedRanges
     From  - To
     10000 - 50000
    250000 - 275000
    350000 - 400000

我想从上面2个表中选择新范围。输出范围将是:

InventoryRanges
 From  - To
     1 - 9999
 50001 - 100000
200000 - 249999
275001 - 300000

如何从范围表中选择这些范围。

我尝试过的事情:

或者,我尝试将所有单独的接收序列号生成为sequence表,并将已调度的序列号标记为true。 基于此表,我正在分组并能够检索InventoryRanges。但是对于这些,我需要存储所有序列号并在分发期间更新较大的范围,这会减慢分发过程。

2 个答案:

答案 0 :(得分:1)

假设您的表结构是这样的:

create table received_ranges(received_date date, [from] int, [to] int);
create table dispatched_ranges(dispatched_date date, [from] int, [to] int);

,并且还假设Received_ranges或dispatched_ranges表中的每个日期都不会有多个条目(根据提供的数据进行假设),此查询将对您有效:

select date, inventory_from, inventory_to from
(select 
rr.received_date as 'date',
case when rr.[from] = dr.[from] then
     0
     else
      rr.[from] 
     end AS 'inventory_from',
case when rr.[from] = dr.[from] then
     0
     else
      dr.[from] - 1
     end AS 'inventory_to'
     from
received_ranges rr left join
dispatched_ranges dr
on
rr.received_date = dr.dispatched_date

UNION

Select 
rr.received_date as 'date',
case when rr.[to] = dr.[to] then 
     0
     else
      dr.[to]+1 
     end AS 'inventory_from',
case when rr.[to] = dr.[to] then
     0
     else
     rr.[to]
     end AS 'inventory_to'
     from
received_ranges rr left join
dispatched_ranges dr
on
rr.received_date = dr.dispatched_date) result
where (inventory_from == 0 and inventory_to == 0) <> TRUE
order by inventory_from;

答案 1 :(得分:1)

我认为这将涵盖您所有发现SQL范围之间差异的情况。希望这对您有所帮助:

create table received_ranges(item_id int, [from] int, [to] int);
create table dispatched_ranges(item_id int, [from] int, [to] int);

insert into received_ranges (item_id,[from],[to]) values
(1, 1,5000),
(1, 7000,8000),
(2, 6000,9000),
(3, 10000,15000),
(4, 20000,25000);

insert into dispatched_ranges (item_id,[from],[to]) values
(1, 1,250),
(2, 6000,7250),
(2, 7500,8000),
(2, 8200, 9000),
(3, 12000,14000),
(4, 20000,25000);


with dispatched_batch(dispatched_batch_num, received_item, received_from, received_to, dispatched_item, dispatched_from, dispatched_to) as
(select row_number() over (partition by rr.item_id, rr.[from] order by rr.[from]) dispatched_batch_num,
rr.item_id as received_item,
rr.[from] as received_from,
rr.[to] as received_to,
dr.item_id as dispatched_item,
dr.[from] as dispatched_from,
dr.[to] as dispatched_to
from received_ranges rr
left join
dispatched_ranges dr
ON
rr.item_id = dr.item_id
AND
dr.[from] >= rr.[from]
AND
dr.[to] <= rr.[to])
select * from
(select
[current].[received_item],
case when [next].dispatched_batch_num is null then
       case when [current].[received_to] <> [current].[dispatched_to] then
              [current].dispatched_to + 1 
            else
              0
            end
     else
       case when [next].[dispatched_from] <> [current].[dispatched_to]+1 then
              [current].[dispatched_to] + 1
            else
              0 
            end
     end
      as 'inventory from',
case when [next].dispatched_batch_num is null then
       case when [current].[received_to] <> [current].[dispatched_to] then
              [current].received_to
            else
              0
            end
     else
       case when [next].[dispatched_from] <> [current].[dispatched_to]+1 then
              [next].[dispatched_from] - 1
            else
              0 
            end
     end
      as 'inventory to'

from dispatched_batch [current]
left join
dispatched_batch [next]
on
[current].received_item = [next].received_item
and 
[current].dispatched_batch_num + 1 = [next].dispatched_batch_num

UNION

select 
[current].received_item,
case when [current].[dispatched_from] is null then
       [current].[received_from]
       else
       case when [previous].dispatched_batch_num is null then
              case when [current].[received_from] <> [current].[dispatched_from] then
                     [current].received_from 
                   else
                     0
                   end
            else
              case when [previous].[dispatched_to] <> [current].[dispatched_from]+1 then
                     [previous].[dispatched_to] + 1
                   else
                     0 
                   end
            end
        end
      as 'inventory from',
case when [current].[dispatched_to] is null then
       [current].[received_to]
       else
       case when [previous].dispatched_batch_num is null then
              case when [current].[received_from] <> [current].[dispatched_from] then
                     [current].dispatched_from -1
                   else
                     0
                   end
            else
              case when [previous].[dispatched_to] <> [current].[dispatched_from]+1 then
                     [current].[dispatched_from] - 1
                   else
                     0 
                   end
            end
        end
      as 'inventory to'

from dispatched_batch [current]
left join
dispatched_batch previous
on
[current].received_item = previous.received_item
and 
[current].dispatched_batch_num  = previous.dispatched_batch_num + 1) result
where [inventory from] <> 0;