Reputation: 10775
I have a table price period tblPricePeriod
in which I have the Amount
to be charged between two dates for a particular apartment.
I have also StartDate
and EndDate
columns for the price period with ApartmentId
.
Below is the structure of my table:
Now I want to calculate to charge the total amount for days of booking.
For example, if someone stays from 4feb to 7 feb then he has to pay according to following scheme:
4- 10
5- 10
6- 10
7 - nothing as this is checkout date
-----------------------------------------------------
totamt--- 30$
I have startdate
and enddate
and apartmentid
as parameter, I am using ms access db.
Now I am using c# code to traverse this with follow code but not successed.
I am getting the amount for all the dates one by one and adding them in one global variable.
The code is as follows:
decimal amount = 0;
// loop to traverse all days between start date and end date
for (DateTime d = Convert.ToDateTime(StartDate); d < Convert.ToDateTime(EndDate); d = d.AddDays(1))
{
string priceCalc = "select Amount from tblPricePeriod where ApartmentId=" + ApartmenId + " and cdate(StartDate) <='" + d.ToShortDateString() + "' and cdate(EndDate) >= '" + d.ToShortDateString() + "'";
DataSet dsPriceCalc = SqlHelper.ExecuteDataset(Connection.ConnectionString, CommandType.Text, priceCalc);
if (dsPriceCalc.Tables[0].Rows.Count > 0)
{
amount = amount + Convert.ToDecimal(dsPriceCalc.Tables[0].Rows[0]["Amount"]);
}
}
Upvotes: 0
Views: 227
Reputation: 850
SELECT
SUM((
IIF(EndDate < @EndDate, EndDate, IIF(@EndDate < StartDate, StartDate, @EndDate)) -
IIF(StartDate > @StartDate, StartDate, IIF(@StartDate > EndDate, EndDate, @StartDate))
) * Amount)
FROM tblPricePeriod
This takes the same sort of approach as GarethD. It's certainly shorter but you could argue which shows the intent clearer. I couldn't test this as I don't have access but I believe it has the IIF statement. The @EndDate parameter needs to be your end date - 1. So in your example I would pass @End Date = 6 Feb.
The IIF statements basically calculate the number of days that need to be counted within each period.
Upvotes: 0
Reputation: 69789
You could adopt an entirely SQL approach:
SELECT SUM(TotalAmount) AS Amount
FROM ( SELECT Amount * (1 + DATEDIFF('d', @StartDate, EndDate)) AS TotalAmount,
(1 + DATEDIFF('d', @StartDate, EndDate)) AS Days,
Amount AS DailyRate
FROM tblPricePeriod
WHERE @StartDate >= StartDate
AND @StartDate <= EndDate
AND @EndDate > EndDate
AND ApartmentID = @ApartmentID
UNION ALL
SELECT Amount * (DATEDIFF('d', @StartDate, @EndDate)), DATEDIFF('d', @StartDate, @EndDate), Amount
FROM tblPricePeriod
WHERE @StartDate >= StartDate
AND @StartDate <= EndDate
AND @EndDate >= StartDate
AND @EndDate <= EndDate
AND ApartmentID = @ApartmentID
UNION ALL
SELECT Amount * (1 + DATEDIFF('d', StartDate, EndDate)), (1 + DATEDIFF('d', StartDate, EndDate)) , Amount
FROM tblPricePeriod
WHERE @StartDate < StartDate
AND @EndDate > EndDate
AND ApartmentID = @ApartmentID
UNION ALL
SELECT Amount * (DATEDIFF('d', StartDate, @EndDate)), DATEDIFF('d', StartDate, @EndDate) , Amount
FROM tblPricePeriod
WHERE @StartDate < StartDate
AND @EndDate <= EndDate
AND @EndDate > StartDate
AND ApartmentID = @ApartmentID
) AS Data
Since Access does not allow comments I've not neen able to annotate the query. The subquery has 4 parts, the top part is for when the Price Period End Date occurs during a visit, the second for when the visit falls entirely within 1 price period, the 3rd for when the visit crosses an entire price period, and the 4th for when the price period starts during a visit. Hope this is clear.
All you would then need to do is add the parameters @ApartmentID, @StartDate and @EndDate to your ExecuteDataset
Method which is a better approach than concatenating strings anyway.
Upvotes: 0
Reputation: 2236
Here is an example of the SUM Function in Sql:
SELECT SUM(salary) as "Total Salary"
FROM employees
WHERE salary > 25000;
//EDIT:
Instead of looping over your DateTimes you can select the Sum of the Amount directly:
DateTime dtStartDate = Convert.ToDateTime(StartDate);
DateTime dtEndDate = Convert.ToDateTime(EndDate); // maybe -1 day
string priceCalc = "select SUM( Amount ) from tblPricePeriod where ApartmentId=" + ApartmenId + " and cdate(StartDate) <= '" + dtStartDate.ToShortDateString( ) + "' and cDate(EndDate) >= '" + dtEndDate.ToShortDateString( ) + "'";
Upvotes: 1