加快加入字符串字段
speed up join on string field
我有一个 table 数据,例如下面的 tableA 示例。日期列被格式化为字符串。
关闭列是一个整数,代码格式为字符串。
我正尝试在 mysql 数据库上 运行 下面的查询,这需要很长时间。
我能做些什么来加快速度吗,比如更改日期列的格式,或者添加
索引还是主键? ticker 和 date 的组合应该是唯一值,date 字段是时间戳,目前只是格式化为字符串。
代码:
select avg((a.close-b.close)/b.close) as avg_annual_returns,
a.ticker
from tableA a
join tableA b
on cast(a.date as date)=date_add(cast(b.date as date),interval 365 DAY)
and a.ticker=b.ticker
where b.close is not null
group by a.ticker
table一个
+--------+-----+------+
|date |close|ticker|
+--------+-----+------+
|2/1/2019|5 |abc |
+--------+-----+------+
|2/3/2019|7 |efd |
+--------+-----+------+
|2/4/2019|3 |hij |
+--------+-----+------+
更新答案:
select ticker,date, ( -1 +
a.close / max(a.close) over (partition by ticker
order by date
range between interval 365 day preceding and interval 365 day preceding
)
) as annual_returns
from tableA a
) b where annual_returns is not null
group by ticker
如果您想要与一年前的不同,请使用 window 函数。不过,在此之前,请修复数据模型!不要将日期存储为字符串。所以:
alter table talbeA modify column date date;
然后得到一年前的收盘价:
select( -1 +
a.close / max(a.close) over (partition by ticker
order by date
range between interval 365 day preceding and interval 365 day preceding
)
)
from tablea a;
您不必担心 NULL
值,因为 AVG()
会忽略它们。
Here 是一个 db<>fiddle.
问题出在这里:
on cast(a.date as date)=date_add(cast(b.date as date),interval 365 DAY)
它的两边都不是“sargeable”,所以它不能使用任何索引。
假设 date
是数据类型 DATE
,那么这有效:
ON a.date = b.date - INTERVAL 1 YEAR
还有
INDEX(ticker, date) -- in this order.
注意:1 YEAR
将在 2 月 28 日左右出现问题; 365 DAY
每4年打嗝366天
另外,改变
where b.close is not null
至
WHERE b.ticker IS NOT NULL
(在功能上它们是相同的,但我在索引中选择了一个列,以防万一。)好吧,有没有 close
为 NULL 的行?
哦,另一个问题。因为周末,每周只有3、4天可以找到上一年的匹配日。
我有一个 table 数据,例如下面的 tableA 示例。日期列被格式化为字符串。
关闭列是一个整数,代码格式为字符串。
我正尝试在 mysql 数据库上 运行 下面的查询,这需要很长时间。
我能做些什么来加快速度吗,比如更改日期列的格式,或者添加
索引还是主键? ticker 和 date 的组合应该是唯一值,date 字段是时间戳,目前只是格式化为字符串。
代码:
select avg((a.close-b.close)/b.close) as avg_annual_returns,
a.ticker
from tableA a
join tableA b
on cast(a.date as date)=date_add(cast(b.date as date),interval 365 DAY)
and a.ticker=b.ticker
where b.close is not null
group by a.ticker
table一个
+--------+-----+------+
|date |close|ticker|
+--------+-----+------+
|2/1/2019|5 |abc |
+--------+-----+------+
|2/3/2019|7 |efd |
+--------+-----+------+
|2/4/2019|3 |hij |
+--------+-----+------+
更新答案:
select ticker,date, ( -1 +
a.close / max(a.close) over (partition by ticker
order by date
range between interval 365 day preceding and interval 365 day preceding
)
) as annual_returns
from tableA a
) b where annual_returns is not null
group by ticker
如果您想要与一年前的不同,请使用 window 函数。不过,在此之前,请修复数据模型!不要将日期存储为字符串。所以:
alter table talbeA modify column date date;
然后得到一年前的收盘价:
select( -1 +
a.close / max(a.close) over (partition by ticker
order by date
range between interval 365 day preceding and interval 365 day preceding
)
)
from tablea a;
您不必担心 NULL
值,因为 AVG()
会忽略它们。
Here 是一个 db<>fiddle.
问题出在这里:
on cast(a.date as date)=date_add(cast(b.date as date),interval 365 DAY)
它的两边都不是“sargeable”,所以它不能使用任何索引。
假设 date
是数据类型 DATE
,那么这有效:
ON a.date = b.date - INTERVAL 1 YEAR
还有
INDEX(ticker, date) -- in this order.
注意:1 YEAR
将在 2 月 28 日左右出现问题; 365 DAY
每4年打嗝366天
另外,改变
where b.close is not null
至
WHERE b.ticker IS NOT NULL
(在功能上它们是相同的,但我在索引中选择了一个列,以防万一。)好吧,有没有 close
为 NULL 的行?
哦,另一个问题。因为周末,每周只有3、4天可以找到上一年的匹配日。