如何在SQL中为每一行拆分数字?

时间:2018-09-25 00:56:03

标签: sql sql-server

我实际上正在努力为每一行分配数量编号。

示例:

每个容器的总数:29

由于某些原因,第一批的最大限制为10,第二批的最大限制为69

我试图像下面这样编写查询,但是返回错误。

select case when totalQ < 29.5 then Quantity else Quantity
end as Quantity, lotno, totalQ  from (
select quantity - 29.5 as totalQ,
* from TestB where id in (
select id from TestA where id =20))A

enter image description here

但是,我期望如下所示:

enter image description here

有人可以帮我解决这个问题吗?

谢谢!

3 个答案:

答案 0 :(得分:3)

尝试这样的事情:

create table TestB ( BatchID varchar(10), TotalQuantity int )

insert into TestB ( BatchID, TotalQuantity ) values
( 'A', 70 ), ( 'B', 10 ), ( 'C', 69 ), ( 'D', 100 ),
( 'E',  0 ), ( 'F', 29 ), ( 'G', 58 ), ( 'H', 200 )

; with 
A as
  ( select BatchID, 
           case when TotalQuantity >= 29 then 29 else TotalQuantity end as Quantity,
           case when TotalQuantity >= 29 then TotalQuantity - 29 else 0 end as Remaining
    from TestB 

    union all

    select BatchID, 
           case when Remaining >= 29 then 29 else Remaining end as Quantity,
           case when Remaining >= 29 then Remaining - 29 else 0 end as Remaining
    from A
    where Remaining > 0 )

    select BatchID, 
           Quantity 
    from A 
    order by BatchID, 
             Quantity desc
    option ( MaxRecursion 1000 )

答案 1 :(得分:2)

大卫的答案非常好。这是使用SQL存储过程的更长的答案。

示例在这里:http://rextester.com/VUQXVQ46335

存储过程

create table test (batch varchar(20), quantity int);
insert into test values ('lot0', 29), ('lot1', 30), ('lot2', 28), ('lot3', 100);
go

create procedure CreateBatches (@BatchSize int)
as
begin

  -- declare variables and create a temporary table
  set nocount on
  declare @v_batch varchar(20), @v_quantity int
  create table #tempTest (batch varchar(20), quantity int)

  -- loop through all records
  declare testCursor cursor for select * from test
  open testCursor
  fetch next from testCursor into @v_batch, @v_quantity

  -- process each record
  while @@fetch_status = 0
  begin
      -- if quantity is larger than the bucket, insert the batch size in the table
      -- reduce the quantity and continue looping
      while @v_quantity > @BatchSize
      begin
        insert into #tempTest values (@v_batch, @BatchSize)
        set @v_quantity = @v_quantity - @BatchSize
      end

      -- store the quantity lower than the batch size in the table
      insert into #tempTest values (@v_batch, @v_quantity)
      fetch next from testCursor into @v_batch, @v_quantity
  end

  select * from #tempTest
  drop table #tempTest
  close testCursor
  deallocate testCursor
  set nocount off

end;
go

结果

exec CreateBatches 32;

#   batch   quantity
1   lot0    29
2   lot1    30
3   lot2    28
4   lot3    32
5   lot3    32
6   lot3    32
7   lot3    4

另一次跑步

exec CreateBatches 29;

#   batch   quantity
1   lot0    29
2   lot1    29
3   lot1    1
4   lot2    28
5   lot3    29
6   lot3    29
7   lot3    29
8   lot3    13

此方法为您提供了一些灵活性,并且使您对批处理系统的工作原理有了更多的了解。处理大量数据时,存储过程可能会变慢。

比较

我对David的递归CTE和存储过程进行了比较。我创建了3031个批次/批次/记录,从第1个批次的500个数量开始,第2个批次的600个数量...第3031个批次的... 303500。

结果

结果以秒为单位。破折号表示查询在12秒后被中止。

Batch size  CTE    SP
----------  -----  -----
300000      1.46s  1.66s
200000      1.61s  1.88s
100000      2.27s  2.47s
 50000      5.00s  5.41s
 25000      7.71s  8.05s
 12500      -      -

这些只是对右旋糖酐的粗略结果测试。您可以看到存储过程比CTE慢。

答案 2 :(得分:0)

使用自我加入和联合

select t.batch,t.quantity from t join t t1 on t.batch=t1.batch
union 
select t.batch,t.totalQ from t join t t1 on t.batch=t1.batch