我正在为MySQL的租赁公司开展一个项目。在简化视图中,我有三个表。一个持有房屋数据,一个有可用性,第三个持有价格。
价格是这里的棘手部分,因为不同数量的人可能会有不同的价格。例如。租房1(蓝屋)最多可容纳4人,比5至10人便宜。在房子的价格旁边,通常每人都有额外的价格。
房屋表:
+----+--------------+----------+
| id | name | max_pers |
+----+--------------+----------+
| 1 | Blue house | 10 |
| 2 | Red house | 8 |
| 3 | Yellow house | 8 |
| 4 | Grey house | 4 |
+----+--------------+----------+
可用性表:
+----+----------+------------+------------+
| id | house_id | from_date | to_date |
+----+----------+------------+------------+
| 1 | 1 | 2017-07-01 | 2017-07-14 |
| 2 | 1 | 2017-08-05 | 2017-08-19 |
| 3 | 2 | 2017-09-02 | 2017-09-16 |
| 4 | 3 | 2017-07-08 | 2017-07-14 |
| 5 | 4 | 2017-08-05 | 2017-08-12 |
| 6 | 4 | 2017-08-26 | 2017-09-02 |
+----+----------+------------+------------+
价格表:
+----+----------+------------+------------+----------+--------+--------------+
| id | house_id | from_date | to_date | max_pers | price | add_per_pers |
+----+----------+------------+------------+----------+--------+--------------+
| 1 | 1 | 2017-07-01 | 2017-07-08 | 4 | 110.00 | 15.00 |
| 2 | 1 | 2017-07-01 | 2017-07-08 | 10 | 140.00 | 10.00 |
| 3 | 1 | 2017-07-08 | 2017-07-14 | 4 | 120.00 | 15.00 |
| 4 | 1 | 2017-07-08 | 2017-07-14 | 10 | 150.00 | 10.00 |
| 5 | 1 | 2017-08-05 | 2017-08-12 | 4 | 130.00 | 20.00 |
| 6 | 1 | 2017-08-12 | 2017-08-19 | 10 | 180.00 | 15.00 |
| 7 | 2 | 2017-09-02 | 2017-09-09 | 8 | 210.00 | 30.00 |
| 8 | 2 | 2017-09-09 | 2017-09-16 | 8 | 220.00 | 30.00 |
| 9 | 3 | 2017-07-08 | 2017-07-14 | 6 | 300.00 | 40.00 |
| 10 | 3 | 2017-07-08 | 2017-07-14 | 8 | 360.00 | 50.00 |
| 11 | 4 | 2017-08-05 | 2017-08-12 | 4 | 80.00 | null |
| 12 | 4 | 2018-08-26 | 2017-09-02 | 4 | 90.00 | null |
+----+----------+------------+------------+----------+--------+--------------+
此测试数据库can be downloaded here的SQL转储。
目标
我正在尝试撰写的查询,应该选择人员< = max_pers以及房屋可用的房屋,然后从具有最低允许max_pers数量的价格表中获取ONE价格。例如。在2017-07-01这一周查看4人住宅1(蓝屋)的价格时,应该给出110作为价格。查询应返回房屋ID,价格和每人的额外费用。
我的努力
我得到了房屋ID和价格,只抓住了正确的价格。
SELECT h.id AS house_id,
(SELECT price
FROM prices AS p
WHERE p.house_id = h.id
AND p.from_date = '2017-07-08'
AND p.to_date = '2017-07-14'
AND p.max_pers >= 6
ORDER BY p.max_pers
LIMIT 1) AS price
FROM houses AS h
INNER JOIN availability a
ON h.id = a.house_id
WHERE h.max_pers >= 6
AND (a.from_date <= '2017-07-08'
AND a.to_date >= '2017-07-14');
返回:
+----------+--------+
| house_id | price |
+----------+--------+
| 1 | 150.00 |
| 3 | 360.00 |
+----------+--------+
这样可行,但是......我现在陷入了如何从价格表中添加add_per_pers列的问题。我尝试添加JOIN而不是select ... as。这样我可以添加字段,但是我不能将数据从价格限制到第一个。
我最好的尝试:
SELECT h.id AS house_id, p.price, p.add_per_pers
FROM houses AS h
INNER JOIN availability a
ON h.id = a.house_id
INNER JOIN prices p
ON h.id = p.house_id
WHERE h.max_pers >= 6
AND (a.from_date <= '2017-07-08'
AND a.to_date >= '2017-07-14')
AND p.from_date = '2017-07-08'
AND p.to_date = '2017-07-14'
AND p.max_pers >= 6;
结果(第三行不应该在那里)
+----------+--------+--------------+
| house_id | price | add_per_pers |
+----------+--------+--------------+
| 1 | 150.00 | 10.00 |
| 3 | 300.00 | 40.00 |
| 3 | 360.00 | 50.00 |
+----------+--------+--------------+
期望的结果
请帮助我得到这个理想的结果:
+----------+--------+--------------+
| house_id | price | add_per_pers |
+----------+--------+--------------+
| 1 | 150.00 | 10.00 |
| 3 | 360.00 | 40.00 |
+----------+--------+--------------+
答案 0 :(得分:1)
如果我理解得很清楚,你只需要Prices
中具有最小max_pers
值的记录。如果这样你可以首先找到每个house_id和相应的最小人数超过最小值日期,然后加入。这样的事情应该做到
SELECT h.id AS house_id, p.price, p.add_per_pers
FROM houses AS h
INNER JOIN availability a
ON h.id = a.house_id
INNER JOIN prices p
ON h.id = p.house_id
INNER JOIN (
SELECT MIN(max_pers) AS max_pers
FROM `Prices` WHERE from_date = '2017-07-08'
AND to_date = '2017-07-14' AND max_pers>=6
GROUP BY house_id) temp
ON p.`max_pers` = temp.`max_pers`
WHERE h.max_pers >= 6
AND (a.from_date <= '2017-07-08'
AND a.to_date >= '2017-07-14')
AND p.from_date = '2017-07-08'
AND p.to_date = '2017-07-14'
AND p.max_pers >= 6
答案 1 :(得分:0)
如果价格的规模和精确度得到修复,这个技巧就会起作用
SELECT house_id, pp, (pp DIV 10000)/100 price, (pp%10000)/100 add_per_pers
FROM (
SELECT h.id AS house_id,
(SELECT CAST(price*1000000 + add_per_pers*100 AS UNSIGNED) pp
FROM prices AS p
WHERE p.house_id = h.id
AND p.from_date = '2017-07-08'
AND p.to_date = '2017-07-14'
AND p.max_pers >= 6
ORDER BY p.price
LIMIT 1) AS pp
FROM houses AS h
INNER JOIN availability a
ON h.id = a.house_id
WHERE h.max_pers >= 6
AND (a.from_date <= '2017-07-08'
AND a.to_date >= '2017-07-14')
) t;