我有一个名为location的表,它与rates表有一对多的关系。 以下是费率表的说明:
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| location_id | bigint(20) | YES | MUL | NULL | |
| price | double | NO | | NULL | |
| start_date | datetime | NO | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
我如何获得最近start_date的最新价格?我尝试了很多查询,以下查询就是其中之一,但我仍然无法得到正确的结果:
SELECT *
FROM rate r
INNER JOIN (SELECT r2.start_date,r2.id AS id,
r2.location_id,
MIN(ABS(DATEDIFF(r2.start_date, NOW()))) AS version
FROM rate r2
GROUP BY r2.location_id) o2
ON (o2.id = r.id AND r.start_date = o2.start_date);
我做错了什么?我该如何解决?
答案 0 :(得分:1)
我会猜测你的数据结构。我猜你有很多地方的定价。我猜你每个地方都有过去和未来的定价。
因此,如果您希望每个位置都有所谓的“当前”价格,那么此查询就可以获得它。这将以当前价格为每个不同的位置返回一行。
SELECT a.id, a.price, a.location, a.start_date
FROM rate a
JOIN (
SELECT location, MAX(start_date) start_date
FROM rate
WHERE start_date <= NOW()
GROUP BY location
) b USING(location, start_date)
(start_date, location, price, id)
上的索引可以很好地加快此查询。
将子查询加入原始表可能看起来很奇怪。但是,如果您需要price
和id
列,那么这是必要的。为什么?因为子查询是一个聚合(GROUP BY
)查询,只能为每个位置返回一个start_date
。它所能做的只是确定适当的日期。 JOIN
恢复表中的其他列。
答案 1 :(得分:1)
这个问题大约每周出现一次,只是有不同的数据。我的最新答案是here。
您的查询将如下所示:
select l.*, r.price
from location l
join rate r
on r.Location_ID = l.ID
and r.Start_Date =(
select Max( Start_Date )
from rate
where Location_ID = r.Location_ID );
您可以允许Start_Date的未来日期,这是提前安排费率更改的时间。在这种情况下,子查询需要稍微更改才能提取当前费率,这是过去的最新费率:
...
where Location_ID = r.Location_ID
and Start_Date <= CurDate() );
假设Rate表的PK是(Location_ID,Start_Date),这个索引将提供你正在寻找的确切行的非常快速的查找。
是的,我可以看到Rate表的PK是代理键。馊主意。你曾经或者你认为你将使用代理键值访问Rate表吗?看看你自己的查询。您有Location_ID来访问Rate表 - 现在是Start_Date值。这两个字段构成了一个自然的唯一键,它们也是您访问表时手头的值。有你最好的主键。
答案 2 :(得分:0)
SELECT *
FROM rate r
GROUP BY r.location_id
ORDER BY r.start_date DESC
我相信这可以在没有加入的情况下发挥作用。
你可能需要包装它,我不记得MySQL是否允许GROUP BY之后的ORDER BY。如果没有,那么这应该有效:
SELECT r.* FROM (SELECT * FROM rate ORDER BY start_date DESC) r GROUP BY r.location_id
答案 3 :(得分:0)
我可能误解了这个问题,但看起来您正试图获取每个location_id的最新开始日期。如果是这种情况,那么我认为以下应该通过使用子查询来获取每个location_id的最大(最近)日期,然后将其连接到自身以获得其余列(id,price)。您的查询执行类似的操作,但它包含子查询中的价格和ID。由于您只是通过location_id查找最近的日期,因此必须将其余列排除在子查询之外,并在确定最近的日期后将其重新引入。
SELECT
r.id,
r.location_id,
r.price,
r.start_date
FROM (SELECT
location_id,
MAX(start_date) as MaxStartDate
FROM rate
GROUP BY location_id
) mr
JOIN rate r
ON r.location_id = mr.location_id
AND r.start_date = mr.MaxStartDate
答案 4 :(得分:0)
我如何获得最近的start_date的最新价格?
如果您想使用最近的start_date
获取任何价格,请尝试此操作SELECT price
FROM location
ORDER BY start_date DESC
LIMIT 1
试试这个,如果你想用最近的start_date获取所有价格,用。分隔 逗号并按其值排序
SELECT GROUP_CONCAT(price ORDER BY price)
FROM location
GROUP BY start_date
ORDER BY start_date DESC
LIMIT 1
它未经过测试,但您可以将其作为进一步研究的基础