0

さて、この手順での私の目標は、支払い約束の最大日と一致する最大金額の支払い約束を見つけることです。これが引っ張る手順を含めるつもりなので、ここには 2 つの手順が表示されます。

この最初の手順は、私がやりたいこととほぼ同じですが、2 つの問題があります。同じ日付の PaymentPromise テーブルに 2 つの値があり、その日付が最大値である場合、両方の値が返されます。PaymentPromise に値がなく、残高がまだ残っている場合、これは PaymentPromise の下に null 値で返される必要がありますが、そうではありません。

ご存知の通り、SQL Server 2008 です。

ALTER PROCEDURE dbo.GetPaymentsDue
(
@Username varchar(20)
)
AS
DECLARE @BondAmounts TABLE
(
BondID bigint,
BondAmount money,
BondTotal money,
BondBalance money
)

INSERT INTO @BondAmounts EXEC dbo.GetBondAmounts @Username = @Username

SELECT bonds.BondID, Bond.Agency, Bond.Agent, Bond.Defendant, Promise.ExpectedDate,
Promise.ExpectedAmount, bonds.BondTotal, bonds.BondBalance
FROM @BondAmounts bonds
INNER JOIN Bond ON bonds.BondID = Bond.ID
LEFT OUTER JOIN
(
    SELECT ID, BondID, ExpectedAmount, ExpectedDate, MAX(ExpectedDate) OVER (PARTITION BY BondID) MaxDate
    FROM PaymentPromise
) Promise ON bonds.BondID = Promise.BondID
WHERE bonds.BondBalance > 0
AND (Promise.ExpectedDate = Promise.MaxDate OR Promise.ExpectedDate = NULL)

したがって、この最初のプロシージャーは 2 番目のプロシージャーを呼び出して、処理する初期データ セットを取得します。

ALTER PROCEDURE dbo.GetBondAmounts
(
@Username varchar(20)
)
AS
SELECT Bond.ID BondID, (ISNULL(Powers.Amount,0) + ISNULL(Charges.Amount,0)) BondAmount,
(ISNULL(BondFee.Amount,0) + ISNULL(Powers.Premium,0) + ISNULL(Charges.Premium,0)
+ ISNULL(Forfeiture.CostOfApprehension,0) + ISNULL(Forfeiture.AmountPaid,0) + Bond.StateTax) BondTotal,
(ISNULL(BondFee.Amount,0) + ISNULL(Powers.Premium,0) + ISNULL(Charges.Premium,0)
+ ISNULL(Forfeiture.CostOfApprehension,0) + ISNULL(Forfeiture.AmountPaid,0) + Bond.StateTax
- ISNULL(BalanceForgiveness.Amount,0) - ISNULL(Payment.Amount,0)) BondBalance
FROM Bond
LEFT OUTER JOIN
(
    SELECT Agency, Username FROM UserAgency
    WHERE Username = @Username
) AS UserAgency ON Bond.Agency = UserAgency.Agency
LEFT OUTER JOIN
(
    SELECT BondID, SUM(AmountForgiven) Amount
    FROM BalanceForgiveness
    GROUP BY BondID
) AS BalanceForgiveness ON Bond.ID = BalanceForgiveness.BondID
LEFT OUTER JOIN
(
    SELECT Bond, SUM(Amount) Amount
    FROM BondFee
    GROUP BY Bond
) AS BondFee ON Bond.ID = BondFee.Bond
LEFT OUTER JOIN
(
    SELECT Powers.Bond, SUM(Charge.BondAmount) Amount,
    ISNULL(SUM(Charge.BondPremium), 0) Premium
    FROM Powers INNER JOIN Charge ON Powers.Surety = Charge.PowerSurety
    AND Powers.PowerPrefix = Charge.PowerPrefix AND Powers.PowerNumber = Charge.PowerNumber
    GROUP BY Bond
) AS Powers ON Bond.ID = Powers.Bond
LEFT OUTER JOIN
(
    SELECT BondID, SUM(BondAmount) Amount, SUM(BondPremium) Premium
    FROM ChargeWithoutPower
    GROUP BY BondID
) AS Charges ON Bond.ID = Charges.BondID
LEFT OUTER JOIN
(
    SELECT Bond, SUM(CostOfApprehension) CostOfApprehension, SUM(AmountPaid) AmountPaid
    FROM Forfeiture
    GROUP BY Bond
) AS Forfeiture ON Bond.ID = Forfeiture.Bond
LEFT OUTER JOIN
(
    SELECT Bond, SUM(Amount) Amount
    FROM Payment
    GROUP BY Bond
) AS Payment ON Bond.ID = Payment.Bond
WHERE UserAgency.Username = @Username
OR EXISTS (SELECT * FROM Users WHERE Username = @Username AND Admin = 1)
4

1 に答える 1

1

クエリに従うのは非常に困難です。最大値が必要な場合に 1 つの行を取得するための一般的な戦略を次に示します。

with t as (select t.*,
                  row_number() over (partition by <whatever> order by paymentpromisedate desc) as seqnum
           from t
          )
select t.*
from t
where seqnum = 1

2 つ目は、おそらく結合ではなく左外部結合の問題です。

問題がどこにあるか (最初または 2 番目のクエリ) を絞り込むことができれば、より詳細な回答を提供しやすくなります。

クエリに適用されます。. .

SELECT bonds.BondID, Bond.Agency, Bond.Agent, Bond.Defendant, Promise.ExpectedDate,
       Promise.ExpectedAmount, bonds.BondTotal, bonds.BondBalance
FROM @BondAmounts bonds INNER JOIN
     Bond
     ON bonds.BondID = Bond.ID LEFT OUTER JOIN
     (SELECT ID, BondID, ExpectedAmount, ExpectedDate,
             row_number() over (partition by bondid order by expectedDate desc) as seqnum
      FROM PaymentPromise
     ) Promise
     ON bonds.BondID = Promise.BondID
WHERE bonds.BondBalance > 0 and
      (Promise.seqnum = 1 or Promise.seqnum is null)

左結合が機能しない理由がわかりません。私はそれについて考えています。

于 2012-07-25T18:30:21.733 に答える