MySQL查询将值与前一行的值进行比较

Posted

技术标签:

【中文标题】MySQL查询将值与前一行的值进行比较【英文标题】:MySQL query comparing values to previous rows' values 【发布时间】:2014-11-07 22:58:33 【问题描述】:

我一直在寻找,但一直找不到解决方案——我知道这是可行的,但我只是没有我需要的 ninja SQL 技能(还)......

我正在寻找解决此问题的方法:我有 2 个与股市数据相关的表格。第一个是带有 ID 和股票代码 (ID,SYMBOL) 的股票代码的简单列表。第二个表包含每只股票的历史价格数据。 (ID、日期、开盘、高、低、关、音量)。

我试图弄清楚如何查询最近收盘价高于 5 个交易日前收盘价的股票。我不能只做日期数学,因为股票不是每天都交易(周末和节假日不交易,有些股票可能不会在正常交易日交易)。因此,我只需要比较每个交易品种最近一行的收盘价和第五行的收盘价。

我在这里有示例表和数据: http://sqlfiddle.com/#!2/5fe76/2

CREATE TABLE `STOCKS` (
  `ID` int,
  `SYMBOL` varchar(10)
);

INSERT INTO `STOCKS` (`ID`,`SYMBOL`)
VALUES
  (1, 'AA'),
  (2, 'ADT'),
  (3, 'AEO'),
  (4, 'AFA');

CREATE TABLE `PRICES` (
    `ID` int,
    `DATE` date,
    `OPEN` decimal(6,2),
    `HIGH` decimal(6,2),
    `LOW` decimal(6,2),
    `CLOSE` decimal(6,2),
    `VOLUME` bigint
  );

INSERT INTO `PRICES` (`ID`,`DATE`,`OPEN`,`HIGH`,`LOW`,`CLOSE`,`VOLUME`) VALUES
(1, '2014-11-06',   16.37,  16.42,  16.15,  16.37,  14200400),
(1, '2014-11-05',   16.68,  16.69,  16.17,  16.26,  18198200),
(1, '2014-11-04',   16.85,  16.87,  16.43,  16.56,  13182800),
(1, '2014-11-03',   16.78,  17.03,  16.65,  16.93,  15938500),
(1, '2014-10-31',   16.43,  16.76,  16.24,  16.76,  18618300),
(1, '2014-10-30',   16.17,  16.36,  15.83,  16.22,  17854400),
(1, '2014-10-29',   16.58,  16.70,  16.05,  16.27,  31173000),
(1, '2014-10-28',   16.5,   16.65,  16.41,  16.60,  12305900),
(1, '2014-10-27',   16.56,  16.57,  16.31,  16.38,  15452900),
(1, '2014-10-24',   16.33,  16.57,  16.22,  16.55,  12840200),

(2, '2014-11-06',   35.9,   36.12,  35.75,  36.07,  1018100),
(2, '2014-11-05',   35.68,  35.99,  35.37,  35.96,  1101500),
(2, '2014-11-04',   35.13,  35.69,  35.02,  35.49,  819100),
(2, '2014-11-03',   35.81,  35.99,  35.27,  35.32,  1304500),
(2, '2014-10-31',   35.79,  35.86,  35.46,  35.84,  1319400),
(2, '2014-10-30',   34.7,   35.34,  34.66,  35.19,  1201800),
(2, '2014-10-29',   35.06,  35.56,  34.5,   34.92,  1359000),
(2, '2014-10-28',   34.32,  35.17,  34.15,  35.07,  1301800),
(2, '2014-10-27',   34.2,   34.2,   33.66,  34.1,   662600),
(2, '2014-10-24',   34.02,  34.54,  33.95,  34.5,   750600),

(3, '2014-11-06',   13.27,  13.92,  13.25,  13.82,  6518000),
(3, '2014-11-05',   12.95,  13.27,  12.74,  13.22,  8716700),
(3, '2014-11-04',   12.85,  12.94,  12.65,  12.89,  4541200),
(3, '2014-11-03',   12.91,  13.12,  12.73,  12.89,  4299100),
(3, '2014-10-31',   13.2,   13.23,  12.83,  12.87,  7274700),
(3, '2014-10-30',   12.83,  12.91,  12.68,  12.86,  4444300),
(3, '2014-10-29',   13.02,  13.20,  12.79,  12.91,  2974900),
(3, '2014-10-28',   12.87,  13.10,  12.52,  13.04,  7365600),
(3, '2014-10-27',   12.84,  13.00,  12.67,  12.92,  6647900),
(3, '2014-10-24',   13.26,  13.29,  12.60,  12.92,  12803300),

(4, '2014-11-06',   24.59,  24.59,  24.49,  24.55,  20400),
(4, '2014-11-05',   24.81,  24.9,   24.81,  24.88,  11800),
(4, '2014-11-04',   24.87,  24.88,  24.76,  24.88,  10600),
(4, '2014-11-03',   24.85,  24.88,  24.76,  24.81,  18100),
(4, '2014-10-31',   24.82,  24.85,  24.77,  24.78,  8100),
(4, '2014-10-30',   24.83,  24.87,  24.74,  24.79,  13900),
(4, '2014-10-29',   24.86,  24.86,  24.78,  24.81,  5500),
(4, '2014-10-28',   24.85,  24.85,  24.80,  24.84,  10600),
(4, '2014-10-27',   24.68,  24.85,  24.68,  24.85,  7700),
(4, '2014-10-24',   24.67,  24.82,  24.59,  24.82,  9300);

查询的伪代码如下所示: "查找最近收盘价高于 5 个交易日前收盘价的交易品种"

我要创建的查询应产生以下结果:

Date        Symbol   Close   Close(-5)
2014-11-06  AA       16.37   16.22
2014-11-06  ADT      36.07   35.19
2014-11-06  AEO      13.82   12.86

(符号 'AFA' 不匹配,因为它最近的收盘价是 24.55,前 5 行是 24.75)

【问题讨论】:

所以你想找到 a) 每只股票的最新价格但 b) 只关注那些价格高于 5 天前的股票?但是,如果 5 天前没有价格怎么办!?! 既然符号是唯一且(可能)不变的,为什么要存储 id 而不是符号!?! 我想我明白为什么 ADT 和 AEO 在结果中,但不是 AA 对于你的第一个问题......我的原始描述可能不够清楚。我想抓住那些价格高于 5 个交易日前的人,而不是 5 个日历日前的人。交易日被简单地定义为 PRICE 表中的前 5 行。 符号名称偶尔会改变,因此会存储一个 id。 【参考方案1】:

您可以使用相关子查询获取 5 天前的价格。实际上,您可以通过相同的方式获得最新价格。所以,这可能是正确的道路:

  select s.*,
         (select p.close
          from prices p
          where p.id = s.id
          order by date desc
          limit 1
         ) as Close,
         (select p.close
          from prices p
          where p.id = s.id and p.date <= date(now()) - interval 5 day
          order by date desc
          limit 1
         ) as Close_5
  from stocks s
  having Close > Close_5;

【讨论】:

戈登 - 谢谢你的回答。不幸的是,基于日期的偏移量并非在所有情况下都有效,因为周末和节假日等某些日子不是交易日。子查询需要选择最近 5 个收盘价——这就是让我难过的部分 :) @paul 我认为你应该相应地修改你的问题 @Paul 。 . .我认为您应该问另一个问题,并更清楚地了解您在约会方面面临的问题。 @GordonLinoff 在原版中。问题它说“日期数学”不会工作,因为日期有差距。所以我会说这不是“日期问题”。由于我无法弄清楚这一点,也许我没有问正确的问题;关于如何使这一点更清楚的任何建议?试图煮沸...我需要选择最近收盘价大于收盘价 5-ROWS 之前的股票代码(行按日期排序,但每行中的日期不是连续天- - 日期中有“空白”)。非常感谢任何有关如何使问题更清楚的指导,谢谢! :)

以上是关于MySQL查询将值与前一行的值进行比较的主要内容,如果未能解决你的问题,请参考以下文章

将值与mysql中表的所有字段进行比较[重复]

将值与mysql中表的所有字段进行比较[重复]

在 MySql 中,有没有办法将值与列中的数字进行比较?

M Power Query - 通过将值与两个参考列进行比较,有条件地转换动态列数中的值

如何在python中将输入值与mysql数据库值进行比较

MySQL 时间序列数据库,跟踪数量/价格/数据历史——仅当新值与前一个不同时才插入新行?