sql >> データベース >  >> RDS >> Sqlserver

特定の値に等しい特定の列の合計で行をグループ化

    実行中の合計が計算されたソース テーブルに適用される「期日」の境界を定義するヘルパー テーブルを使用して、各実行中の合計額と「期日」の境界との交点を計算できます。

    With Receipt As ( --< Sample source table
        Select * From (Values
            ('R1', 100),
            ('R2', 100),
            ('R3',  70),
            ('R4',  50),
            ('R5', 200)
        ) V (ReceiptNo, Amount)
    ), ReceiptWithTotal As ( --< Source table with Running Totals calculated
        Select *,
            SUM(Amount) Over (Order By ReceiptNo Rows Unbounded Preceding) - Amount As RunningTotalBefore,
            SUM(Amount) Over (Order By ReceiptNo Rows Unbounded Preceding) As RunningTotalAfter
        From Receipt
    ), Due As ( --< Helper table to define intervals (can be generated dynamically to cover any Total)
        Select * From (Values
            ('D1',   0, 100),
            ('D2', 100, 200),
            ('D3', 200, 300),
            ('D4', 300, 400),
            ('D5', 400, 500),
            ('D6', 500, 600)
        ) V (DueNo, AmountLow, AmountHigh)
    )
    Select DueNo, ReceiptNo,
        IIF(AmountHigh < RunningTotalAfter, AmountHigh, RunningTotalAfter) -
        IIF(AmountLow > RunningTotalBefore, AmountLow, RunningTotalBefore) As Amount
    From Due
    Inner Join ReceiptWithTotal On NOT (RunningTotalAfter <= AmountLow OR RunningTotalBefore >= AmountHigh)
      

    注意:SUM(...) Over (Order By ... Rows Unbounded Preceding) および IIF(...) SQL Server 2012+ でのみ使用できます。サブクエリを使用して SQL Server 2008 でも同じことができますが、効率は大幅に低下します:

    With Receipt As ( --< Sample source table
        Select * From (Values
            ('R1', 100),
            ('R2', 100),
            ('R3',  70),
            ('R4',  50),
            ('R5', 200)
        ) V (ReceiptNo, Amount)
    ), ReceiptWithTotal As ( --< Source table with Running Totals calculated
        Select *, RunningTotalAfter - Amount As RunningTotalBefore
        From (
            Select *,
                (Select SUM(Amount) From Receipt B Where B.ReceiptNo <= A.ReceiptNo) As RunningTotalAfter
            From Receipt A
        ) A
    ), Due As ( --< Helper table to define intervals (can be generated dynamically to cover any Total)
        Select * From (Values
            ('D1',   0, 100),
            ('D2', 100, 200),
            ('D3', 200, 300),
            ('D4', 300, 400),
            ('D5', 400, 500),
            ('D6', 500, 600)
        ) V (DueNo, AmountLow, AmountHigh)
    )
    Select DueNo, ReceiptNo,
        CASE WHEN AmountHigh < RunningTotalAfter THEN AmountHigh ELSE RunningTotalAfter END -
        CASE WHEN AmountLow > RunningTotalBefore THEN AmountLow ELSE RunningTotalBefore END As Amount
    From Due
    Inner Join ReceiptWithTotal On NOT (RunningTotalAfter <= AmountLow OR RunningTotalBefore >= AmountHigh)
      


    1. MySQLレプリケーションを使用したMoodleの高可用性データベースの構築

    2. Sqliteでの挿入クエリの問題?(変数挿入)

    3. PostgresENUMデータ型またはCHECKCONSTRAINT?

    4. 再起動後にXAMPPMySQLサービスがクラッシュする