加快加入字符串字段

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天可以找到上一年的匹配日。