简体   繁体   English

从SQL中的位置表获取最新价格

[英]Get Latest Price from Location table in SQL

I have a table called location which has one to many relations with rates table. 我有一个名为location的表,它与rate表具有一对多的关系。 The following is a description of the rate table: 以下是费率表的说明:

+-------------+--------------+------+-----+---------+----------------+
| 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    |                |
+-------------+--------------+------+-----+---------+----------------+

How could I get the latest price which has most recent start_date? 如何获得具有最近start_date的最新价格? I tried many queries the following query is one of them, but I still can't get the correct result: 我尝试了许多查询,以下查询是其中之一,但仍然无法获得正确的结果:

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);

What am I doing wrong? 我究竟做错了什么? how can I fix it? 我该如何解决?

I'll take a guess at your data structure. 我将猜测您的数据结构。 I will guess that you have pricing for many locations. 我想您会为许多地区定价。 I will guess that you have both past and future pricing for each location. 我想您对每个位置都有过去和将来的价格。

So, if you want the so-called "current" price for each location, this query gets it. 因此,如果您想要每个位置的所谓“当前”价格,则此查询将得到它。 This will give back one row for each distinct location with the current price. 这将以当前价格为每个不同的位置返回一行。

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)

An index on (start_date, location, price, id) will accelerate this query nicely. 索引(start_date, location, price, id)将很好地加速此查询。

It may seem strange to have to join the subquery back to the original table. 必须将子查询重新连接到原始表似乎很奇怪。 But, if you want the price and id columns, that's necessary. 但是,如果您想要priceid列,那是必需的。 Why? 为什么? Because the subquery is an aggregate ( GROUP BY ) query that can only return a single start_date for each location. 因为子查询是一个聚合( GROUP BY )查询,所以每个位置只能返回一个start_date All it can do is identify the appropriate date. 它所能做的就是确定适当的日期。 The JOIN recovers the other columns from the table. JOIN从表中恢复其他列。

This question appears about once a week, just with different data. 这个问题大约每周出现一次,只是数据不同。 My latest answer is here . 我的最新答案是在这里

Your query will look like this: 您的查询将如下所示:

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 );

You could allow future dates for Start_Date, for time when a rate change is scheduled ahead of time. 您可以允许Start_Date的将来日期,以便提前安排费率更改的时间。 In that case, the subquery would need a slight change to pull out the current rate which is the latest rate still in the past: 在这种情况下,子查询可能需要稍作更改以提取当前汇率,该汇率是过去的最新汇率:

        ...
        where   Location_ID = r.Location_ID
            and Start_Date <= CurDate() );

Assuming the PK of the Rate table is (Location_ID, Start_Date), this index will provide very fast lookup of the exact row you're looking for. 假设费率表的PK为(Location_ID,Start_Date),则此索引将非常快速地查找您要查找的确切行。

Yes, I can see the PK for the Rate table is a surrogate key. 是的,我可以看到“费率”表的PK是代理键。 Bad idea. 馊主意。 Have you ever or do you think you will ever access the Rate table using the surrogate key value? 你有没有或者你认为你使用代理键的值曾经访问费率表? Look at your own query. 查看您自己的查询。 You have the Location_ID to access the Rate table -- and now the Start_Date value. 您具有Location_ID来访问Rate表-现在是Start_Date值。 Those two fields form a natural unique key and they are also the values you will have on hand when you access the table. 这两个字段构成一个自然的唯一键,它们也是您访问表时将拥有的值。 There is your best primary key. 有你最好的主键。

SELECT *
FROM rate r
GROUP BY r.location_id
ORDER BY r.start_date DESC

I believe this would work without a join. 我相信,如果没有加入,这将奏效。

You might need to wrap this, I can't remember if MySQL allows an ORDER BY after a GROUP BY. 您可能需要包装一下,我不记得MySQL在GROUP BY之后是否允许ORDER BY。 If it doesn't then this should work: 如果没有,那应该可以:

SELECT r.* FROM (SELECT * FROM rate ORDER BY start_date DESC) r GROUP BY r.location_id

I may be misunderstanding the question but it looks like you are trying to get the most recent start date for each location_id. 我可能对这个问题有误解,但看来您正在尝试获取每个location_id的最新开始日期。 If that is the case then I believe the following should work by using a subquery to get the maximum (most recent) date for each location_id and then joining it on itself to get the rest of the columns (id, price). 如果是这种情况,那么我认为下面的方法应该可以通过使用子查询来获取每个location_id的最长(最新)日期,然后将其自身联接以获取其余的列(id,价格)来工作。 Your query does something similar but it includes the price and id in the subquery. 您的查询执行类似的操作,但在子查询中包含价格和ID。 Since you're only looking for the most recent date by location_id the rest of the columns must be left out of the subquery and brought back in after you determine the most recent date. 由于您仅通过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

How could I get the latest price which has most recent start_date? 如何获得具有最近start_date的最新价格?

Try this, if you want to fetch any of price with recent start_date 如果您想获取最近start_date的价格,请尝试此操作

SELECT price
FROM location
ORDER BY start_date DESC
LIMIT 1

Try this, if you want to fetch all prices with recent start_date, separated with commas and sorted by their values 如果要获取最近的start_date的所有价格,请用逗号分隔并按其值排序,请尝试此操作

SELECT GROUP_CONCAT(price ORDER BY price)
FROM location
GROUP BY start_date
ORDER BY start_date DESC
LIMIT 1

It's not tested, but you may use it as foundation for futher researches 它未经测试,但您可以将其用作进一步研究的基础

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM