[英]Calculate price given standard rates and seasonal date ranges
我正在建立一個預訂風格系統。 這些房間的年費率是標准的(這是我的問題與其他類似的問題有所不同,因為其他人具有獨特的范圍),然后它們在一年中的日期范圍也設置為不同的價格。 我希望在MYSQL中計算價格,但是當用戶選擇的日期在特殊日期范圍內時,既要對該價格求和,又要對這些日期的標准價格求和,這意味着總數太高了。 這有點羅word,所以這里是查詢和示例:
SELECT SUM(Price * (1 + DATEDIFF(LEAST(End_date, '2015-07-25' - INTERVAL 1 DAY), GREATEST(Start_date, '2015-07-15')))) AS Total
FROM room_rates
WHERE roomId = '46' AND (
'2015-07-25' - INTERVAL 1 DAY BETWEEN Start_date AND End_date
OR '2015-07-15' BETWEEN Start_date AND End_date
)
+--------+------------+------------+------------+------+
| RoomId | Range Name | Start_Date | End_Date | Rate |
+--------+------------+------------+------------+------+
| 46 | Standard | 2015-01-01 | 2015-12-31 | 100 |
+--------+------------+------------+------------+------+
| 46 | Summer | 2015-07-20 | 2015-08-31 | 150 |
+--------+------------+------------+------------+------+
| 46 | Christmas | 2015-12-18 | 2015-12-31 | 180 |
+--------+------------+------------+------------+------+
如果用戶在我的查詢示例中選擇2015-07-15至2015-07-25,則我要這樣計算:
總計應為1250。 但是,由於“標准費率”的日期介於一年的第一天和最后一天之間,因此查詢還包括該價格以及夏季日期范圍內該范圍內的價格和總費率,這意味着我將按標准費率收取所有10個日期的費用,加上夏季房價5晚,總計1750。
所以我的問題是,如果沒有其他選擇,我該如何修改查詢以僅使用標准費率? 標准費率始終稱為“標准費率”,因此我可以輕松識別它們,我只是不知道要進行哪些更改!
編輯
我應該添加,我正在PHP中進行此操作(我正在使用PDO)
第二次編輯同樣值得注意的是,日期范圍將始終落在一年之內,並且日期范圍不能重疊(標准費率會占用整整一年)
解
決定更改我的方法,並遵循幾個人提出的答案,並建立一個日常數據庫。 這是我最后的有效查詢。 感謝大家的幫助和建議。
SELECT standard_rates.villaId as `villaId`,
sum(IFNULL(custom_rates.nightly_rate_usd, standard_rates.nightly_rate_usd))
AS `Rate`
FROM dates
LEFT JOIN
villa_price_bands AS standard_rates
ON standard_rates.Name = 'Standard'
AND dates.date BETWEEN standard_rates.Start_Date AND standard_rates.End_Date
AND FIND_IN_SET(standard_rates.villaId, :resultIds)
LEFT JOIN
villa_price_bands AS custom_rates
ON custom_rates.Name != 'Standard'
AND dates.date BETWEEN custom_rates.Start_Date AND custom_rates.End_Date
AND custom_rates.villaId = standard_rates.villaId
WHERE dates.date >= :arrDate
AND dates.date < :deptDate
GROUP BY villaId
我將使用一個日期表:一個由一列( date
)組成的表( datelist
),其中包含前n年和未來n年的所有日期。
查詢的粗略概述(您可能需要更正結束日期):
SELECT
datelist.date AS Night,
IFNULL(seasonal_rates.Range_Name, standard_rates.Range_Name) AS Season,
IFNULL(seasonal_rates.Rate, standard_rates.Rate) AS Rate
FROM datelist
LEFT JOIN rates AS standard_rates ON standard_rates.Range_Name = 'Standard'
LEFT JOIN rates AS seasonal_rates ON datelist.date BETWEEN seasonal_rates.Start_Date AND seasonal_rates.End_Date
WHERE standard_rates.RoomId = 46
AND seasonal_rates.RoomId = 46
AND datelist.date BETWEEN '2015-07-15' AND '2015-07-25'
然后,您可以將結果傳遞到SUM / GROUP BY查詢中。
使用MySQL CASE語句。
例如
SELECT Columnname,
sum(CASE
WHEN RangeName LIKE '%Standard%'
THEN do something END) as AliasName
FROM YourTable
我之前處理此類問題的方式是構建“日期”表。
1990年1月1日.. 1/1/2050(您可以一次完成,但是由於存儲空間為數Mb,“真實”表的性能提升值得進行一次設置。
例如。
|Date ID| Date |
|---------------------|
|0000001| 2015-01-01 |
|0000002| 2015-01-02 |
那么您可以基於此構建視圖。 如:
Select
[date id],
if(range_name='standard',rate,0) standardPrices,
if(range_name='Summer',rate,0) summerPrices,
if(range_name='Winter',rate,0) winterPrices
from
date_table left join room_rates
on date_table.date between start_date and end_date
where room = '46' and date_table.date between '2015-07-15' and '2015-07-25'
給你一個像
date |standardPrices|summerPrices|winterPrices|
------------------------------------------------------
2015-07-15 | 100 | 0 | 0 |
2015-07-16 | 100 | 0 | 0 |
2015-07-17 | 100 | 0 | 0 |
2015-07-18 | 100 | 0 | 0 |
2015-07-19 | 100 | 0 | 0 |
2015-07-20 | 100 | 0 | 0 |
2015-07-20 | 0 | 150 | 0 |
2015-07-21 | 100 | 0 | 0 |
2015-07-21 | 0 | 150 | 0 |
如果您然后將此視圖按“日期”分組; 您可以依次使用它來運行查詢以進行匯總(再次使用'if(summerPrices> 0,summerPrices,standardPrices)
這不是最優雅的解決方案,但它可以正常工作,並且閃電般快速,可以讓您使用聯接而不是循環查詢(我更喜歡這種查詢)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.