Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Help with optimizing complex stored procedure

Author  Topic 

tribune
Posting Yak Master

105 Posts

Posted - 2004-04-26 : 20:46:26

I need to create a line-item invoice for a reservation of a property. SQL server needs to insert a record into a line-item table for each date in the reservation. For example, the finished product for the calculation of a reservation for April 28th - May 5th looks like so:

BookingOrderChargeID BookingOrderID ChargeName ChargeType TotalAmount LineItemNum
-------------------- -------------- -------------------- ---------- ----------- -----------
79 159 Reservation April 28 N 120.00 1
80 159 Reservation April 29 N 120.00 2
81 159 Reservation April 30 N 135.00 3
82 159 Reservation May 1st N 135.00 4
83 159 Reservation May 2nd N 120.00 5
84 159 Reservation May 3rd N 120.00 6
85 159 Reservation May 4th N 120.00 7
86 159 Reservation May 5th N 120.00 8


My date range is defined as:

declare @BeginningStay datetime
declare @EndingStay datetime

And I have two tables (Rates and RatesCustom) with pricing data. Rates contains default prices, and RatesCustom contains custom prices for special dates such as holidays. If custom rates are found, they override the default rates. Each date of the interval is line-item entered into another table (Charges).

Table Layout
=============================================================

Rates
------
RateID (int) (pk)
UnitID (int) (ID for a property that we're calculating for)
DefaultMondayAmount (money)
DefaultTuesdayAmount (money)
....
DefaultSundayAmount (money)

RatesCustom
-----------
RateCustomID (int) (pk)
UnitID (int) (ID for a property that we're calculating for)
CustomDate (datetime)
Amount (money) (this value overrides the default above if record exists)

There is also clustered index on RatesCustom on the fields UnitID, CustomDate, I hope this is right :)

Charges
-------
ChargeID (int) (pk)
OrderID (int)
ChargeName (varchar) (format: "Reservation Month[rd][st][th][nd]")
Amount
LineItemNum
[/quote]



Current Stored Procedure
==================================================================

create proc OnlineBookingChargesGenerate2
(
@BookingOrderID int
)
as
begin

set nocount on

declare @UnitID int -- Unit for booking order
declare @LineItemNum tinyint -- This is our line item number, which is incremented for each charge inserted into OnlineBookingOrderCharges
declare @BeginningStay datetime -- Beginning day of reservation
declare @EndingStay datetime -- Ending day of reservation
declare @BookingOrderChargeID int -- ID of inserted charge, comes from OnlineBookingOrderChargeInsert return value

-- Check for valid Booking Order
if not exists(select BookingOrderID from OnlineBookingOrders where BookingOrderID = @BookingOrderID)
return -1

-- Check to make sure Booking Order's charges have not already been generated (modifications to order may not be done through this procedure)
if exists(select BookingOrderID from OnlineBookingOrderCharges where BookingOrderID = @BookingOrderID)
return -1

-- Assign local variables
select
@BeginningStay = BeginningStay,
@EndingStay = EndingStay,
@UnitID = UnitID
from OnlineBookingOrders
where BookingOrderID = @BookingOrderID

-- Calculate rent charges from reservation

declare @CurrentDate datetime
declare @Quantity tinyint
declare @UnitPrice money
declare @Amount money
set @Quantity = 1
set @CurrentDate = @BeginningStay
set @LineItemNum = 1
while @CurrentDate <= @EndingStay
begin
if exists(select * from RatesCustom where UnitID = @UnitID and CustomDate = @CurrentDate)
begin
-- insert line-item charge
insert into OnlineBookingOrderCharges
(
BookingOrderID,
ChargeName,
ChargeType,
ChargeStatus,
UnitPrice,
Quantity,
TotalAmount,
LineItemNum
)
select
@BookingOrderID,
'Reservation ' + datename(m, @CurrentDate) + ' ' + datename(d, @CurrentDate) +
case
when datename(d, @CurrentDate) IN ('1', '21', '31') then 'st'
when datename(d, @CurrentDate) IN ('2', '22') then 'nd'
when datename(d, @CurrentDate) IN ('3', '23') then 'rd'
ELSE 'th'
end,
'N',
'A',
Amount,
@Quantity,
Amount * @Quantity,
@LineItemNum
from RatesCustom
where UnitID = @UnitID and CustomDate = @CurrentDate

-- increment line-item #
set @LineItemNum = @LineItemNum + 1

-- increment current date
set @CurrentDate = DateAdd(d, 1, @CurrentDate)
end
else
begin
-- find our prices from Rates table
select @Amount =
case datename(weekday, @CurrentDate)
when 'Monday' then DefaultMondayAmount
when 'Tuesday' then DefaultTuesdayAmount
when 'Wednesday' then DefaultWednesdayAmount
when 'Thursday' then DefaultThursdayAmount
when 'Friday' then DefaultFridayAmount
when 'Saturday' then DefaultSaturdayAmount
when 'Sunday' then DefaultSundayAmount
end
from Rates
where UnitID = @UnitID
print cast(@Amount as varchar(100))

-- insert line-item charge
insert into OnlineBookingOrderCharges
(
BookingOrderID,
ChargeName,
ChargeType,
ChargeStatus,
UnitPrice,
Quantity,
TotalAmount,
LineItemNum
)
select
@BookingOrderID,
'Reservation ' + datename(m, @CurrentDate) + ' ' + datename(d, @CurrentDate) +
case
when datename(d, @CurrentDate) IN ('1', '21', '31') then 'st'
when datename(d, @CurrentDate) IN ('2', '22') then 'nd'
when datename(d, @CurrentDate) IN ('3', '23') then 'rd'
ELSE 'th'
end,
'N',
'A',
@Amount,
@Quantity,
@Amount * @Quantity,
@LineItemNum

-- increment line-item #
set @LineItemNum = @LineItemNum + 1

-- increment current date
set @CurrentDate = DateAdd(d, 1, @CurrentDate)

end
end

end

=====================================================================
End stored procedure
=====================================================================


My question is how can I avoid the while statement in the stored procedure, or speed up the query in any way. The custom rates table could eventually have 200,000 records, and with a reservation spanning three weeks, thats 4,200,000 queries.

Would it help to redesign the pricing tables?

Much appreciated,
-trib

tribune
Posting Yak Master

105 Posts

Posted - 2004-04-26 : 20:47:59
Alright I'll try this code paste again...




create proc OnlineBookingChargesGenerate2
(
@BookingOrderID int
)
as
begin

set nocount on

declare @UnitID int -- Unit for booking order
declare @LineItemNum tinyint -- This is our line item number, which is incremented for each charge inserted into OnlineBookingOrderCharges
declare @BeginningStay datetime -- Beginning day of reservation
declare @EndingStay datetime -- Ending day of reservation
declare @BookingOrderChargeID int -- ID of inserted charge, comes from OnlineBookingOrderChargeInsert return value

-- Check for valid Booking Order
if not exists(select BookingOrderID from OnlineBookingOrders where BookingOrderID = @BookingOrderID)
return -1

-- Check to make sure Booking Order's charges have not already been generated (modifications to order may not be done through this procedure)
if exists(select BookingOrderID from OnlineBookingOrderCharges where BookingOrderID = @BookingOrderID)
return -1

-- Assign local variables
select
@BeginningStay = BeginningStay,
@EndingStay = EndingStay,
@UnitID = UnitID
from OnlineBookingOrders
where BookingOrderID = @BookingOrderID

-- Calculate rent charges from reservation

declare @CurrentDate datetime
declare @Quantity tinyint
declare @UnitPrice money
declare @Amount money
set @Quantity = 1
set @CurrentDate = @BeginningStay
set @LineItemNum = 1
while @CurrentDate <= @EndingStay
begin
if exists(select * from RatesCustom where UnitID = @UnitID and CustomDate = @CurrentDate)
begin
-- insert line-item charge
insert into OnlineBookingOrderCharges
(
BookingOrderID,
ChargeName,
ChargeType,
ChargeStatus,
UnitPrice,
Quantity,
TotalAmount,
LineItemNum
)
select
@BookingOrderID,
'Reservation ' + datename(m, @CurrentDate) + ' ' + datename(d, @CurrentDate) +
case
when datename(d, @CurrentDate) IN ('1', '21', '31') then 'st'
when datename(d, @CurrentDate) IN ('2', '22') then 'nd'
when datename(d, @CurrentDate) IN ('3', '23') then 'rd'
ELSE 'th'
end,
'N',
'A',
Amount,
@Quantity,
Amount * @Quantity,
@LineItemNum
from RatesCustom
where UnitID = @UnitID and CustomDate = @CurrentDate

-- increment line-item #
set @LineItemNum = @LineItemNum + 1

-- increment current date
set @CurrentDate = DateAdd(d, 1, @CurrentDate)
end
else
begin
-- find our prices from Rates table
select @Amount =
case datename(weekday, @CurrentDate)
when 'Monday' then DefaultMondayAmount
when 'Tuesday' then DefaultTuesdayAmount
when 'Wednesday' then DefaultWednesdayAmount
when 'Thursday' then DefaultThursdayAmount
when 'Friday' then DefaultFridayAmount
when 'Saturday' then DefaultSaturdayAmount
when 'Sunday' then DefaultSundayAmount
end
from Rates
where UnitID = @UnitID
print cast(@Amount as varchar(100))

-- insert line-item charge
insert into OnlineBookingOrderCharges
(
BookingOrderID,
ChargeName,
ChargeType,
ChargeStatus,
UnitPrice,
Quantity,
TotalAmount,
LineItemNum
)
select
@BookingOrderID,
'Reservation ' + datename(m, @CurrentDate) + ' ' + datename(d, @CurrentDate) +
case
when datename(d, @CurrentDate) IN ('1', '21', '31') then 'st'
when datename(d, @CurrentDate) IN ('2', '22') then 'nd'
when datename(d, @CurrentDate) IN ('3', '23') then 'rd'
ELSE 'th'
end,
'N',
'A',
@Amount,
@Quantity,
@Amount * @Quantity,
@LineItemNum

-- increment line-item #
set @LineItemNum = @LineItemNum + 1

-- increment current date
set @CurrentDate = DateAdd(d, 1, @CurrentDate)

end
end


end
Go to Top of Page

tribune
Posting Yak Master

105 Posts

Posted - 2004-04-28 : 12:24:18
anyone?
Go to Top of Page
   

- Advertisement -