简体   繁体   English

MySQL查询获取给定DateTime之前的两个最新记录

[英]MySQL query to get two most recent records before a given DateTime

I have an application that keeps track of prices for various products. 我有一个可以跟踪各种产品价格的应用程序。 Prices might change for any given product at any time during any day, and will not change regularly. 在一天中的任何时候,任何给定产品的价格可能会发生变化,并且不会定期变化。 There is a PriceHistory table that has dated records for all of the prices for the products over time. 有一个PriceHistory表,该表具有日期记录的产品随时间变化的所有价格。 Users of the application can select a time and date and see what the prices were at that time. 应用程序的用户可以选择时间和日期,并查看当时的价格。 I use a query like this to get the "current" prices for all products at any given day and time: 我使用这样的查询来获取任何给定日期和时间的所有产品的“当前”价格:

SELECT A.*
FROM `PriceHistory` A
INNER JOIN (
    SELECT `BrandKey`, `LocationKey`, `ProductKey`, max(`EffectiveDateTime`) AS MaxUpdateDate
    FROM `PriceHistory`
    WHERE `EffectiveDateTime` <= '2010-02-22 12:00:00'
    GROUP BY `BrandKey`, `LocationKey`, `ProductKey`
) AS B ON 
A.`BrandKey` = B.`BrandKey`
AND A.`LocationKey` = B.`LocationKey`
AND A.`ProductKey` = B.`ProductKey`
AND A.`EffectiveDateTime` = B.MaxUpdateDate

Now I need to be able to show users how much the price changed when that price went into effect. 现在,我需要向用户展示价格生效后价格发生了多少变化。 So I need to get the two most recent prices for the selected time instead of just one. 因此,我需要获取所选时间的两个最新价格,而不是一个。 I'm pretty stumped. 我很沮丧。 I've tried a couple of things and I'm just getting SQL errors because my attempted joins aren't legal. 我已经尝试了几件事,但由于遇到不合法的联接,我刚遇到SQL错误。 Any help would be appreciated. 任何帮助,将不胜感激。

I can loop over all the products and get the two most recent prices, but that's taking about 10 seconds for 350 products and 75,000 price rows. 我可以遍历所有产品并获得两个最新价格,但是对于350个产品和75,000个价格行来说,这大约需要10秒钟。 I don't necessarily need all products in one query, but running queries for each product won't be fast enough. 我并不一定需要在一个查询中使用所有产品,但是对每个产品运行查询都不够快。

I would break it into 2 selects.. 我将其分为2个选择。

1st - select max( EffectiveDateTime ) ... from price history where EffectiveDateTime <= '2010-02-22 12:00:00' 1-从价格历史记录中选择max( EffectiveDateTime )...,其中EffectiveDateTime <='2010-02-22 12:00:00'

step 2 ) This requires that you have a numeric (autoinc type) PK in the priceHistory table. 步骤2)这要求您在priceHistory表中具有数字(自动递增类型)PK。 add it if it doesn't exist. 如果不存在,请添加。 Assume this column is called PriceHistoryID 假设此列称为PriceHistoryID

part a) grab all the numeric PK's from the last query, and implode them into a var $ignoreRows 部分a)从上一个查询中获取所有数字PK,并将其内嵌到var $ ignoreRows中

part b) get the max date ignoring the most recent set of data that you want to diff against .. ie get the second to last most recent data. b)部分获得最大日期,而忽略要与之比较的最新数据集。即获取倒数第二个最新数据。

select max( EffectiveDateTime ) ... from price history where EffectiveDateTime <= '2010-02-22 12:00:00' AND priceHistoryID NOT IN ($ignoreRows) 从价格历史记录中选择max( EffectiveDateTime )...,其中EffectiveDateTime <='2010-02-22 12:00:00'并且priceHistoryID不在($ ignoreRows)

Note, if you only have 1 data point in the price history, it may not match up 1-1 , but that is a relatively minor thing you can fix in code, I would imagine... 请注意,如果您在价格历史记录中只有1个数据点,则它可能与1-1不匹配,但这是您可以在代码中修复的相对较小的事情,我想...

If an auto_increment column is defined as the last component of a composite key, that column acts as a counter of all rows with the same values. 如果将auto_increment列定义为组合键的最后一个组成部分,则该列将用作所有具有相同值的行的计数器。

EG. 例如。

v1,v2,v3,1
v1,v2,v3,2
v1,v2,v4,1
...

You can use this in a temporary table built from your history table to rank all the entries with the same BrandKey, LocationKey, ProductKey on descending date value. 您可以在由历史记录表构建的临时表中使用此表,以对降序日期值上具有相同BrandKey,LocationKey和ProductKey的所有条目进行排名。

create temporary table ph ( 
    `BrandKey` varchar(10),
    `LocationKey` varchar(10), 
    `ProductKey` varchar(10), 
    `EffectiveDateTime`datetime,
    rank int not null auto_increment,
    primary key(BrandKey, LocationKey, ProductKey, rank);

insert into ph
   select `BrandKey`, `LocationKey`, `ProductKey`, `EffectiveDateTime`, NULL
   FROM `PriceHistory`
   WHERE `EffectiveDateTime` <= '2010-02-22 12:00:00'
   order by EffectiveDateTime desc;

delete from ph where rank > 2;

This temporary table will now contain 1 or 2 rows per BrandKey , LocationKey , ProductKey , which can then easliy be joined against your Price table - using a self (left) join if you need to include both the current and previous price in the same row. 现在,此临时表将每个BrandKeyLocationKeyProductKey包含1或2行,然后可以将它们轻松地与您的Price表进行连接-如果需要在同一行中同时包含当前价格和以前的价格,请使用自(左)连接。

A query against the table, sorted by EffectiveDateTime in DESC order, with LIMIT 2 should do it. 对表的查询(按EffectiveDateTimeDESC顺序排序,并以LIMIT 2进行排序)应该可以做到。

SELECT A.*
FROM `PriceHistory` A
WHERE <clauses for selecting a product and brand go here>
ORDER BY `EffectiveDateTime` DESC
LIMIT 2

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

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