根据前面的行查询行
Query rows based on previous rows
我有一个 table,里面有一些金融价格数据。此数据具有类型('T'、'B' 或 'S' 之一)、时间戳和价格。我需要找到 'T' 类型的行,其价格低于前一个 'B' 类型行的价格或高于前一个 'S' 类型行的价格。
这是一些示例数据:
+-------+------+----------------------------------+---------------+
| id | type | htime | price |
+-------+------+----------------------------------+---------------+
| 4505 | T | 2022-04-24 19:41:00.585891 | 5799.30000000 |
| 4506 | B | 2022-04-24 19:41:00.585891 | 5799.00000000 |
| 4507 | S | 2022-04-24 19:41:00.586754 | 5801.40000000 |
| 4508 | S | 2022-04-24 19:41:00.586802 | 5801.10000000 |
| 4509 | B | 2022-04-24 19:41:00.586818 | 5799.30000000 |
| 4510 | T | 2022-04-24 19:41:00.586820 | 5799.30000000 |
| 4511 | T | 2022-04-24 19:41:00.586820 | 5799.00000000 |
| 4512 | B | 2022-04-24 19:41:00.586820 | 5799.00000000 |
| 4515 | S | 2022-04-24 19:41:00.587087 | 5801.10000000 |
| 4516 | S | 2022-04-24 19:41:00.588252 | 5801.10000000 |
| 4591 | S | 2022-04-24 19:41:00.639867 | 5801.10000000 |
| 4608 | T | 2022-04-24 19:41:00.657640 | 5798.00000000 |
| 4609 | B | 2022-04-24 19:41:00.657640 | 5797.20000000 |
+-------+------+----------------------------------+---------------+
所以在这里我想查询 ID 为 4511 的 return 行(类型 = 'T' 并且价格低于类型 = 'B' 的前一行的价格)和 4608(同样的原因)。我不要第4510行,因为它的价格既不低于前'B'行也不高于前'S'行。我可能只想忽略第 4505 行,但那里发生的事情对我来说并不重要。
我试过以下查询:
WITH bids AS (SELECT * FROM my_table WHERE type = 'B'),
offers AS (SELECT * FROM my_table WHERE type = 'S')
SELECT *
FROM (SELECT * FROM my_table WHERE type = 'T') trades
WHERE trades.price < (SELECT price FROM bids WHERE bids.htime < trades.htime ORDER BY htime DESC LIMIT 1)
OR trades.price > (SELECT price FROM offers WHERE offers.htime < trades.htime ORDER BY htime DESC LIMIT 1);
但是速度非常慢。我希望有一个更简单的自连接类型解决方案,但我对此很陌生。
table 在 (type, htime) 上有一个索引。
我正在使用 MariaDB 10.5.13
您好,欢迎来到 SO!
试试这个查询,理论上应该不会慢。
这个解决方案的想法是在 select 子句中添加一个额外的结果,该结果将使用子查询生成,如果不满足条件,则结果将为 null 或 id符合条件的前一行。
最后,您可以将其包装到一个额外的 select 中,以显示实际符合条件的行。
select results.id, results.previousId from (
select t1.*, (select t2.id from test22 t2
where t1.type = 'T'
and ((t2.type='B' and t1.price<t2.price) or (t2.type='S' and t1.price>t2.price))
and t2.htime<t1.htime order by t2.htime asc limit 1) as previousId
from test22 as t1)
as results
where results.previousId is not null;
我有一个 table,里面有一些金融价格数据。此数据具有类型('T'、'B' 或 'S' 之一)、时间戳和价格。我需要找到 'T' 类型的行,其价格低于前一个 'B' 类型行的价格或高于前一个 'S' 类型行的价格。
这是一些示例数据:
+-------+------+----------------------------------+---------------+
| id | type | htime | price |
+-------+------+----------------------------------+---------------+
| 4505 | T | 2022-04-24 19:41:00.585891 | 5799.30000000 |
| 4506 | B | 2022-04-24 19:41:00.585891 | 5799.00000000 |
| 4507 | S | 2022-04-24 19:41:00.586754 | 5801.40000000 |
| 4508 | S | 2022-04-24 19:41:00.586802 | 5801.10000000 |
| 4509 | B | 2022-04-24 19:41:00.586818 | 5799.30000000 |
| 4510 | T | 2022-04-24 19:41:00.586820 | 5799.30000000 |
| 4511 | T | 2022-04-24 19:41:00.586820 | 5799.00000000 |
| 4512 | B | 2022-04-24 19:41:00.586820 | 5799.00000000 |
| 4515 | S | 2022-04-24 19:41:00.587087 | 5801.10000000 |
| 4516 | S | 2022-04-24 19:41:00.588252 | 5801.10000000 |
| 4591 | S | 2022-04-24 19:41:00.639867 | 5801.10000000 |
| 4608 | T | 2022-04-24 19:41:00.657640 | 5798.00000000 |
| 4609 | B | 2022-04-24 19:41:00.657640 | 5797.20000000 |
+-------+------+----------------------------------+---------------+
所以在这里我想查询 ID 为 4511 的 return 行(类型 = 'T' 并且价格低于类型 = 'B' 的前一行的价格)和 4608(同样的原因)。我不要第4510行,因为它的价格既不低于前'B'行也不高于前'S'行。我可能只想忽略第 4505 行,但那里发生的事情对我来说并不重要。
我试过以下查询:
WITH bids AS (SELECT * FROM my_table WHERE type = 'B'),
offers AS (SELECT * FROM my_table WHERE type = 'S')
SELECT *
FROM (SELECT * FROM my_table WHERE type = 'T') trades
WHERE trades.price < (SELECT price FROM bids WHERE bids.htime < trades.htime ORDER BY htime DESC LIMIT 1)
OR trades.price > (SELECT price FROM offers WHERE offers.htime < trades.htime ORDER BY htime DESC LIMIT 1);
但是速度非常慢。我希望有一个更简单的自连接类型解决方案,但我对此很陌生。
table 在 (type, htime) 上有一个索引。
我正在使用 MariaDB 10.5.13
您好,欢迎来到 SO!
试试这个查询,理论上应该不会慢。
这个解决方案的想法是在 select 子句中添加一个额外的结果,该结果将使用子查询生成,如果不满足条件,则结果将为 null 或 id符合条件的前一行。
最后,您可以将其包装到一个额外的 select 中,以显示实际符合条件的行。
select results.id, results.previousId from (
select t1.*, (select t2.id from test22 t2
where t1.type = 'T'
and ((t2.type='B' and t1.price<t2.price) or (t2.type='S' and t1.price>t2.price))
and t2.htime<t1.htime order by t2.htime asc limit 1) as previousId
from test22 as t1)
as results
where results.previousId is not null;