2012-07-25 132 views
0

好的,因此我通過此過程的目標是找到與付款承諾的最大日期相匹配的最高金額付款承諾。我將包括此處的程序,因此您會在這裏看到2個程序。查找爲SQL Server數據庫中指定的最大日期指定的最大金額

這第一個程序與我想要的操作非常接近,但有兩個問題。如果PaymentPromise表中有兩個具有相同日期的值,並且該日期爲最大值,則會返回兩個值。如果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) 

所以這第一個過程調用第二個過程來獲得初始數據集的工作。

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) 
+0

+1命名參數... – 2012-07-25 17:27:54

回答

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 

第二個可能是一個左外的問題加入,而不是加入。

如果您可以縮小問題的位置 - 第一個或第二個查詢 - 提供更詳細的答案會更容易。

適用於您的查詢。 。 。

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) 

我不確定左連接爲什麼不起作用。我正在考慮。

+0

就像我上面所說的,第一個查詢是問題所在。具體地,在下面的代碼: 'LEFT OUTER JOIN ( SELECT ID,BondID,ExpectedAmount,ExpectedDate,MAX(ExpectedDate)OVER(PARTITION BY BondID)MAXDATE FROM PaymentPromise )無極ON bonds.BondID = Promise.BondID' 它返回預期日期爲最大日期的所有值,但我希望它只返回單個值,即最大預期金額。 – Grungondola 2012-07-25 18:46:25

+0

第二個查詢的目的是讓您知道數據來自何處。第二個查詢由另一個存儲過程使用,並且沒有問題返回我需要的所有值。如果在系統中存在支付承諾,則此值僅返回一個值,但如果在同一最長日期有多個支付承諾,則返回倍數。 – Grungondola 2012-07-25 18:49:04

+0

而不是使用{max(expecteddate)over(partitioned by bondid)}}您應該使用{row_number()over(由bondid分區)order by expecteddate desc)seqnum}。然後選擇「seqnum = 1」而不是「date = maxdate」。 – 2012-07-25 18:50:51