Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何一次选择和导出5000行借贷交易,并使借贷余额为零?_Sql_Sql Server_Tsql_Sql Server 2012 - Fatal编程技术网

Sql 如何一次选择和导出5000行借贷交易,并使借贷余额为零?

Sql 如何一次选择和导出5000行借贷交易,并使借贷余额为零?,sql,sql-server,tsql,sql-server-2012,Sql,Sql Server,Tsql,Sql Server 2012,我们要迁移到的ERP系统要求总账具有5000行或更少行的csv文件。每个文件中的借方和贷方交易必须平衡为零。有多个借方和贷方交易行共享一个公共交易ID 使用offset和fetch next,我一次可以提取5000行,但是借贷不平衡 数据示例: TranID Credit Debit Balance Account# 1 250 0 250 ABC 1 0 250 0 DEF 2 0

我们要迁移到的ERP系统要求总账具有5000行或更少行的csv文件。每个文件中的借方和贷方交易必须平衡为零。有多个借方和贷方交易行共享一个公共交易ID

使用offset和fetch next,我一次可以提取5000行,但是借贷不平衡

数据示例:

TranID  Credit  Debit   Balance Account#
1       250     0       250     ABC
1       0       250     0       DEF
2       0       100     -100    GHI
2       50      0       -50     JKL
2       50      0       0       MNO


declare @batchsize INT = 5000,
    @loopcount INT = 0;

while (@loopcount*@batchsize < (select  count(*) from [Apps2].[dbo].[GLTrans]))
begin
  SELECT *  FROM [Apps2].[dbo].[GLTrans]
  ORDER BY tranID
  offset (@batchsize * @loopcount) rows
  fetch next (@batchsize) rows only

  set @loopcount= @loopcount + 1
end

一个简单的解决方案是预处理所有事务,并为每个CSV文件分配一个批次号。temp表存储了每个TranID的行数

假设每个TranID的借方和贷方将保持平衡

之后,您可以根据临时表生成CSV

-- create the temp table
create table #trans
(
    TranID      int identity,
    Cnt         int,
    Batch       int
)

-- populate the temp table
insert into #trans (TranID, Cnt)
select TranID, Cnt = count(*)
from   [Apps2].[dbo].[GLTrans]
group by TranID

declare @batchsize  int = 5000,
        @batch      int = 1

while   exists (select * from #trans where Batch is null)
begin
    update  t
    set     Batch   = @batch 
    from
    (
        select  *, cumm = sum(Cnt) over (order by TranID)
        from    #trans
        where   Batch   is null
    ) t
    where   cumm    <= @batchsize 

    select  @batch = @batch + 1
end

--  Verify
select  *, sum(Cnt) over (partition by Batch order by TranID)
from    #trans 
order by TranID 

使用表变量迭代数据。有点像在Oracle中使用光标

如果我正确理解了您的示例数据,并且假设每个transID都设置为0,那么您可以更改循环逻辑,使其功能更像do…同时获取下一个事务集,并确定它是否将批处理保持在5k以下。 这应该包括填充一批5000行或更少的行,假设每个事务ID将净值设置为$0,则净值为$0

Declare @batchCursor TABLE (
    TransID INT,
    Credit INT, -- chose int for expediency 
    Debit INT,
    Balance INT,
    AccountNo Varchar(4)

),

@batchsize INT = 5000,
@rowCount INT = 0,
@transID INT = 1,
@transSize INT = 0;

while (@rowcount <= 5000)
BEGIN
    INSERT INTO @batchCursor
    SELECT * FROM [Apps2].[dbo].[GLTrans] -- you might need to enumerate all your column names
    WHERE TransID = @transID;

    SELECT @transSize = COUNT(*) FROM @batchCursor where TransID = @transID);

    IF(@transSize > 0)
        BEGIN
        IF (@transSize + @rowCount < @batchSize)
           BEGIN
           Set @rowCount += transSize;
           Set @transID += 1;
           END;
        END;
    ELSE Set @transID += 1;

IF((Select count(*) FROM [Apps2].[dbo].[GLTrans] WHERE TransID = @transID) + @rowCount > @batch)
BREAK;

END;

那么每笔交易的总和为零?所以问题是如何在不拆分事务的情况下找到尽可能多的行(最多5000行)?是的。您是正确的,在不拆分事务tranid的情况下,将尽可能多的行数增加到5000行。将运行总数与行数和id一起计算到临时表中,然后在运行总数为零的情况下找到小于5000行的最高行数?选择5000行,然后丢弃具有上一个事务id的行。Squirrel,这对我的第一个通行证有效。我的用户希望在我们创建的5000个批次中有一个子批次,将事务拆分为500个或更少的组。我已经尝试在它自己内部重用上面的代码来做这件事,但是一直遇到错误。您对如何实现这一点有何见解?不太了解您对子批次的要求。也许你可以开始一个新的问题并发布你的查询