4

マイナスの日々の残高からプラスになる口座のターンオーバー時間を計算するのに助けが必要です. たとえば、口座 12345 は 2013 年 4 月 5 日にはプラスですが、04/06、04/07、04/08 (3 日間) にはマイナスの残高があり、4 日目にはプラスになりました。その回転時間 (4 日) を計算するクエリを作成したいと思います。

Account Number  Transaction Date    Daily Balance
    12345       4/1/2013            304
    12345       4/2/2013            -78
    12345       4/3/2013            -65
    12345       4/4/2013            12
    12345       4/5/2013            25
    12345       4/6/2013            -345
    12345       4/7/2013            -450
    12345       4/8/2013            -650
    12345       4/9/2013            105
    12345       4/10/2013           110
    110000      4/1/2013            150
    110000      4/2/2013            -15
    110000      4/3/2013            -56
    110000      4/4/2013            -35
    110000      4/5/2013            -15
    110000      4/6/2013            106
    110000      4/7/2013            500
    110000      4/8/2013            -150
    110000      4/9/2013            50
    110000      4/10/2013           100
    55544       4/1/2013            150
    55544       4/2/2013            120
    55544       4/3/2013            -145
    55544       4/4/2013            -250
    55544       4/5/2013            15
    55544       4/6/2013            20
    55544       4/7/2013            40
    55544       4/8/2013            50
    55544       4/9/2013            -10
    55544       4/10/2013           60

上記の表から次の結果を取得しようとしています。クエリは、数千行のトランザクション テーブルに適用されます。したがって、次の結果を計算するための効率的なクエリを作成するには、助けが必要です。

Account Number  Turnover time for an account to become positive
12345           3
12345           4
110000          5
110000          2
55544           3
55544           2

MS SQL サーバー バージョン 2008 を使用しています。

はい、ゼロがあります。そしてそれらは肯定的であると見なされます。つまり、残高がマイナスから0またはプラスに変わったとき、それはターンオーバーと見なされます。

Fadi Hassan が提供するソリューションは、最も効率的で実装が簡単です。口座残高が最初にマイナスの場合など、1つの課題がありますが、機能しません。例えば、残高が-110、-40、0、10、90、30、0、-10、-20、0の場合は動作しません。

ここに画像の説明を入力

誰かがより良い解決策を持っている場合は、親切に助けてください。

4

4 に答える 4

1
;WITH T
     AS (SELECT [Account Number],
                [Transaction Date],
                [Daily Balance],
                MAX([Transaction Date]) 
                          OVER (PARTITION BY [Account Number]) AS FinalAccountTransaction,
                ROW_NUMBER() 
                          OVER (PARTITION BY [Account Number] 
                                    ORDER BY [Transaction Date]) - 
                ROW_NUMBER() 
                          OVER (PARTITION BY [Account Number], 
                                             CASE WHEN [Daily Balance] < 1 THEN 1 END 
                                    ORDER BY [Transaction Date]) AS Grp
         FROM   DailyBalance)
SELECT [Account Number],
       MIN([Transaction Date])                                             AS Start,
       DATEDIFF(DAY, MIN([Transaction Date]), MAX([Transaction Date])) + 2 AS [Turnover time]
FROM   T
WHERE  [Daily Balance] < 1
GROUP  BY [Account Number],
          Grp,
          FinalAccountTransaction
/*If this is the final group then it is not followed by a positive so exclude*/
HAVING MAX([Transaction Date]) <> FinalAccountTransaction
ORDER  BY [Account Number],
          Start 

SQL フィドル

于 2013-09-26T09:35:50.893 に答える
1

これがあなたが探していたものであることを願っています @prem (編集)

    SELECT  *
FROM    (
        SELECT  a.[Account Number],
            a.[Transaction Date],
            a.[Daily Balance],
            DATEDIFF(dd, ISNULL(    (
                        SELECT  MAX(c.[Transaction Date])
                        FROM    Accounts c
                        WHERE   c.[Account Number] = a.[Account Number]
                            AND c.[Transaction Date] < a.[Transaction Date]
                            AND c.[Daily Balance] >= 0
                        ),
                        (
                        SELECT  DATEADD(dd, -1, MIN(c.[Transaction Date]))
                        FROM    Accounts c
                        WHERE c.[Account Number] = a.[Account Number]
                        )
                        ),
            a.[Transaction Date]) AS dat
        FROM    Accounts a
        WHERE a.[Daily Balance] >= 0
    ) t
WHERE   dat > 1
于 2013-04-18T10:03:18.107 に答える
0

カーソルを使用して以下の解決策を確認し、それに応じて列名を変更してください。これがお役に立てば幸いです

-- CREATE temp table with rownum to add row numbers
CREATE TABLE #TurnOverTimeTaken
(
    rownum INT,
    Account_Number INT NULL,
    Daily_Balance INT
)

-- Insert data into the temp table with row number
INSERT INTO #TurnOverTimeTaken
SELECT 
   ROW_NUMBER() OVER(PARTITION BY  Account_Number ORDER BY Account_Number) AS rownum
  ,Account_Number
  ,Daily_Balance
FROM TurnOverTimeTaken

-- Create another temp table to display the result  
CREATE TABLE #Result
(
    Account_Number INT NULL,
    Total INT
)

DECLARE @rownum INT
DECLARE @Account_Number INT
DECLARE @Daily_Balance INT
DECLARE @CurrentVal INT

SET @CurrentVal = 0

--Cursor starts here
DECLARE CountCursor CURSOR 
FOR SELECT rownum, Account_Number, Daily_Balance FROM #TurnOverTimeTaken
OPEN CountCursor
FETCH NEXT FROM CountCursor INTO @rownum, @Account_Number, @Daily_Balance
WHILE @@FETCH_STATUS = 0 
BEGIN
    -- Check Daily_Balance is negative and rownumber is not equal to one and previous Daily_Balance > 0
    IF(@Daily_Balance < 0 AND @rownum <> 1 AND 
    (SELECT Daily_Balance FROM #TurnOverTimeTaken WHERE rownum=@rownum-1 AND Account_Number=@Account_Number) > 0)
    BEGIN
        SET @CurrentVal = @CurrentVal + 1
        INSERT INTO #Result VALUES(@Account_Number, @CurrentVal)
    END
    ELSE IF(@Daily_Balance < 0)
    BEGIN
        INSERT INTO #Result VALUES(@Account_Number, @CurrentVal)
    END

    FETCH NEXT FROM CountCursor INTO @rownum, @Account_Number, @Daily_Balance
END
CLOSE CountCursor
DEALLOCATE CountCursor

--SELECT * FROM #TurnOverTimeTaken

SELECT Account_Number,COUNT(Total)+1 FROM #Result
GROUP BY Account_Number,Total

DROP TABLE #TurnOverTimeTaken
DROP TABLE #Result
于 2013-04-18T09:14:38.680 に答える