SQL根据连续日期获取值的变化
Posted
技术标签:
【中文标题】SQL根据连续日期获取值的变化【英文标题】:SQL get change in values based on consecutive dates 【发布时间】:2012-05-12 11:40:15 【问题描述】:我想获得每天的价格变化。什么 SQL 查询将完成此操作?
原表
Date Company Price
---------------------------
1/4/2012 Apple 458
1/3/2012 Apple 462
1/2/2012 Apple 451
1/1/2012 Apple 450
想要的表
Date Company Price Day_Change
-------------------------------------
1/4/2012 Apple 458 -4
1/3/2012 Apple 462 9
1/2/2012 Apple 451 1
1/1/2012 Apple 450 NULL
【问题讨论】:
您的结果不正确。 451 - 450 = 1(正确),462 - 451 = 9(错误) 【参考方案1】:将表连接到自身以获得该公司昨天的价格,然后从今天的价格中减去它
select
t1.date,
t1.company,
t1.price,
t1.price - t2.price as day_change
from price_table t1
left join price_table t2
on t2.date = subdate(t1.date, 1)
and t2.company = t1.company
在此之后您可以添加一个普通的where
子句,例如where t1.date > subdate(current_date(), 7)
以获取最近 7 天的价格
仅供参考,如果昨天的价格没有一行,day_change
将是 NULL
【讨论】:
关于 仅供参考,如果昨天的价格没有一行,day_change 将为 NULL,请考虑我的回答 :-) ***.com/a/10423889 @MichaelBuen 如果您仔细阅读问题,您会发现NULL
正是他想要的 - 请参阅 OP 示例输出的最后一行 :)
他的NULL
与您的查询相比,并不是因为数据不连续。我推断他的NULL
可能只是表明该行是趋势中的第一行:-) 我也可以这样做;-)
该死,你是对的,虽然你说它在输出的最后一行,但标题说明了一切SQL get change in values based on 连续日期【参考方案2】:
另一种方法,即使在不连续的日期也可以工作:
来源数据:
CREATE TABLE fluctuate
(Date datetime, Company varchar(10), Price int);
INSERT INTO fluctuate
(Date, Company, Price)
VALUES
('2012-01-04 00:00:00', 'Apple', 458),
('2012-01-03 00:00:00', 'Apple', 462),
('2012-01-02 00:00:00', 'Apple', 451),
('2012-01-01 00:00:00', 'Apple', 450),
('2012-01-01 00:00:00', 'Microsoft', 1),
('2012-01-03 00:00:00', 'Microsoft', 7),
('2012-01-05 00:00:00', 'Microsoft', 5),
('2012-01-07 00:00:00', 'Microsoft', 8),
('2012-01-08 00:00:00', 'Microsoft', 12);
输出:
DATE COMPANY PRICE DAY_CHANGE
January, 04 2012 Apple 458 -4
January, 03 2012 Apple 462 11
January, 02 2012 Apple 451 1
January, 01 2012 Apple 450 NULL
January, 08 2012 Microsoft 12 4
January, 07 2012 Microsoft 8 3
January, 05 2012 Microsoft 5 -2
January, 03 2012 Microsoft 7 6
January, 01 2012 Microsoft 1 NULL
查询:
select
date,
company,
price,
day_change
from
(
select
case when company <> @original_company then
-- new company detected,
-- reset the original price based on the new company
@original_price := null
end,
f.*,
price - @original_price as day_change,
(@original_price := price),
(@original_company := company)
from fluctuate f
cross join
(
select
@original_price := null,
@original_company := company
from fluctuate
order by company, date limit 1
)
as zzz
order by company, date
) as yyy
order by company, date desc
来源:http://www.sqlfiddle.com/#!2/56de3/3
【讨论】:
【参考方案3】:@Bohemian 的回答是正确的,将返回自前一天以来的价格差异,但实际上我怀疑您实际上会想要自前一天交易以来的价格差异(可能跨越周末、公共假期)等)。
要做到这一点,必须首先使用子查询来确定每家公司交易的最后一天(个别公司可以暂停交易,或者可能在不同的市场交易受不同的假期);然后使用 (date,company)
对来查找最新价格...
SELECT current.*, current.Price - previous.Price AS Day_Change
FROM (
SELECT yourtable.*, MAX(before.Date) AS prevDate
FROM
yourtable
JOIN yourtable AS before
ON before.Date < yourtable.Date
AND before.Company = yourtable.Company
GROUP BY yourtable.Date, yourtable.Company
) AS current
JOIN yourtable AS previous
ON previous.Date = current.prevDate
AND previous.Company= current.Company
【讨论】:
由于相关子查询(您有“n”个查询),这将表现不佳。最好使用用户定义的变量,并且只在表格上进行一次传递。 没错,这将表现不佳。仅靠基于集合的思维方式无法直接处理某些类型的查询。一个例子,请看 Adam Machanic sqlblog.com/blogs/adam_machanic/archive/2006/07/12/… 的这个运行总和 关于但实际上我怀疑您实际上会想要自前一天交易以来的价格差异(可能跨越周末、公共假期等),请参阅我的方法:@ 987654322@以上是关于SQL根据连续日期获取值的变化的主要内容,如果未能解决你的问题,请参考以下文章
从十进制 (8, 0) 格式的日期获取 n-3 或 n-x 个月(约 90 天前),在 SQL Server 和 DB2 中具有年份变化影响