我们假设我有这些表:
[ properties ]
id (INT, PK)
name (VARCHAR)
[ properties_prices ]
id (INT, PK)
property_id (INT, FK)
date_begin (DATE)
date_end (DATE)
price_per_day (DECIMAL)
price_per_week (DECIMAL)
price_per_month (DECIMAL)
我的访问者会搜索以下内容:列出前一天的10个(分页)属性,其中每天的价格(price_per_day字段)在1月5日到12月31日期间的10到100之间 < / p>
我知道这是一个巨大的查询,我需要对结果进行分页,所以我必须完成所有计算并只在一个查询中登录...这就是我在这里的原因! :)
有关问题的问题
没有差距。所有可能的日期都在数据库中。
在完美世界中,没有......考虑到所有变化/期间,我们需要计算该时期内该类型价格的“总和”。
这只是每页10个结果的分页示例...可以通过FULLTEXT搜索订购,我将添加关键字和这些东西......正如我所说,这是一个非常大的查询。
答案 0 :(得分:2)
这类似于@mdma给出的答案,但我在join子句中使用了一个条件来代替价格范围,而不是HAVING
技巧。
SELECT p.id, MAX(p.name),
MIN(v.price_per_day) AS price_low,
MAX(v.price_per_day) AS price_high
FROM properties p
JOIN properties_prices v ON p.id = v.property_id
AND v.price_per_day BETWEEN 10 AND 100
AND v.date_begin < '2010-12-31' AND v.date_end > '2010-05-01'
GROUP BY p.id
ORDER BY ...
LIMIT 10;
我还建议创建覆盖索引:
CREATE INDEX prices_covering ON properties_prices
(property_id, price_per_day, date_begin, date_end);
这允许您的查询以尽可能最佳的方式运行,因为它可以直接从索引中读取值。它根本不必从表中读取数据行。
+----+-------------+-------+-------+-----------------+-----------------+---------+-----------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-----------------+-----------------+---------+-----------+------+--------------------------+
| 1 | SIMPLE | p | index | PRIMARY | PRIMARY | 4 | NULL | 1 | |
| 1 | SIMPLE | v | ref | prices_covering | prices_covering | 4 | test.p.id | 6 | Using where; Using index |
+----+-------------+-------+-------+-----------------+-----------------+---------+-----------+------+--------------------------+
答案 1 :(得分:1)
你告诉我们的不够精确。从您的数据结构和您的问题我假设:
但仍有疑问:
根据答案的不同,可能没有单一的查询可以解决问题。但是,如果你接受这些差距,那可能会得到你想要的东西:
SELECT *
FROM properties AS p
WHERE EXISTS -- property is available in the price range
(SELECT * FROM properties_prices AS pp1
WHERE p.id = pp1.property_id AND
pp1.price_per_day between 10 and 100 AND
(pp1.date_begin <= "2010-12-31" OR pp1.date_end >= "2010-05-01")) AND
NOT EXISTS -- property is in the price range in all sup-periods, but there might be gaps
(SELECT * FROM properties_prices AS pp2
WHERE p.id = pp2.property_id AND
pp2.price_per_day not between 10 and 100 AND
(pp2.date_begin <= "2010-12-31" OR pp2.date_end >= "2010-05-01"))
ORDER BY name --- ???
LIMIT 10
该查询未向您提供价格或其他详细信息。这需要进行额外的查询。但也许我的假设都是错的。
答案 2 :(得分:1)
这也可以作为GROUP BY来完成,我认为这将是非常有效的,并且我们将一些聚合作为包的一部分:
SELECT
prperty_id, MIN(price_per_day), MAX(price_per_day)
FROM
properties_prices
WHERE
date_begin <= "2010-12-31" AND date_end >= "2010-05-01"
GROUP BY
property_id
HAVING MIN(IF( (price_per_day BETWEEN 10 AND 100), 1, 0))=1
ORDER BY ...
LIMIT 10
(我没有手持MySQL,所以我没有测试过。我不确定MIN(IF ...)但使用CASE的模型在SQLServer上工作。)