首页 > 解决方案 > 如何一次选择并导出 5,000 行借记和贷记交易,并使借记和贷记余额为零?

问题描述

我们要迁移到的 ERP 系统需要为 GL 提供 5,000 行或更少行的 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

标签: sqlsql-servertsqlsql-server-2012

解决方案


使用表变量来遍历您的数据。有点像在 Oracle 中使用游标...

如果我正确理解了您的示例数据并且我假设每个 transID 都将网络设置为 0,那么您可以将循环逻辑更改为更像执行操作...而像这里的示例一样,您可以在其中获取下一个事务集并决定它是否将批次保持在 5k 以下。这应该包括填充一批 5000 行或更少的行,净值为 0 美元,假设每个事务 ID 设置净值为 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;

推荐阅读