【问题标题】:SQL get change in values based on consecutive datesSQL根据连续日期获取值的变化
【发布时间】: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(错误)

标签: mysql sql date join


【解决方案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,请考虑我的回答 :-) stackoverflow.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@
    猜你喜欢
    • 2012-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-19
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多