【发布时间】:2021-09-04 16:25:49
【问题描述】:
编辑:实际上,主要问题是上次更新设置 A.last_52w_high_age_brutto_days(见下文)。是否可以优化此更新或以某种方式集成到 CURSOR 更新中?谢谢。
我有一张包含股市每日价格的表格。
表结构:
CREATE TABLE `cind_stocks_daily_rates` (
`symbol` varchar(12) NOT NULL,
`p_date` int unsigned NOT NULL,
`open_price` decimal(9,4) NOT NULL,
`high_price` decimal(9,4) NOT NULL,
`low_price` decimal(9,4) NOT NULL,
`close_price` decimal(9,4) NOT NULL,
`price_52w_low` decimal(9,4) DEFAULT NULL,
`price_52w_high` decimal(9,4) DEFAULT NULL,
`last_52w_high_age_brutto_days` int unsigned DEFAULT NULL,
PRIMARY KEY (`symbol`,`p_date `)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT 语句:
INSERT INTO cind_stocks_daily_rates (symbol, datum, open_price, high_price, low_price, close_price, price_52w_low, price_52w_high, last_52w_high_age_brutto_days)
VALUES
('DELL', 20210616, 150, 152, 149, 151, 149, 152, 0),
('INTZ', 20210616, 250, 252, 249, 251, 249, 252, 0),
('MSFT', 20210616, 350, 352, 349, 351, 349, 352, 0),
('NTNX', 20210616, 452, 452, 449, 451, 449, 452, 0),
('DELL', 20210617, 148, 151, 147, 150, 147, 152, 1),
('INTZ', 20210617, 251, 254, 250, 252, 249, 254, 0),
('MSFT', 20210617, 346, 349, 345, 347, 345, 352, 1),
('NTNX', 20210617, 450, 454, 450, 453, 449, 454, 0),
('DELL', 20210618, 146, 147, 144, 145, NULL, NULL, NULL),
('INTZ', 20210618, 254, 256, 253, 255, NULL, NULL, NULL),
('MSFT', 20210618, 349, 351, 349, 350, NULL, NULL, NULL),
('NTNX', 20210618, 453, 456, 452, 454, NULL, NULL, NULL);
想要的结果:
symbol datum open_price high_price low_price close_price price_52w_low price_52w_high last_52w_high_age_brutto_days
DELL 20210616 150 152 149 151 149 152 0
INTZ 20210616 250 252 249 251 249 252 0
MSFT 20210616 350 352 349 351 349 352 0
NTNX 20210616 452 452 449 451 449 452 0
DELL 20210617 148 151 147 150 147 152 1
INTZ 20210617 251 254 250 252 249 254 0
MSFT 20210617 346 349 345 347 345 352 1
NTNX 20210617 450 454 450 453 449 454 0
DELL 20210618 146 147 144 145 144 152 2
INTZ 20210618 254 256 253 255 249 256 0
MSFT 20210618 349 351 349 350 345 352 2
NTNX 20210618 453 456 452 454 449 456 0
在表格中填写给定日期的价格/费率后,我想计算过去 52 周的高价和低价 - 以及过去 52 周高价和价值日期列。
我创建了一个光标:
SELECT distinct symbol FROM cind_stocks_daily_rates
WHERE price_52w_low IS NULL OR price_52w_high IS NULL;
并通过光标(curr_symbol)循环符号:
UPDATE cind_stocks_daily_rates AS A
CROSS JOIN
(SELECT AA.p_date, AA.symbol,
Min(AA.low_price) OVER (ORDER BY AA.p_date ROWS BETWEEN 260 PRECEDING AND CURRENT ROW) AS low_price_52w,
Max(AA.high_price) OVER (ORDER BY AA.p_date ROWS BETWEEN 260 PRECEDING AND
CURRENT ROW) AS high_price_52w
FROM cind_stocks_daily_rates AA
WHERE AA.symbol = curr_symbol
ORDER BY AA.p_date) as B ON B.symbol = A.symbol AND B.p_date = A.p_date
SET A.price_52w_low = B.low_price_52w,
A.price_52w_high = B.high_price_52w,
WHERE A.price_52w_low IS NULL OR A.price_52w_high IS NULL;
在光标循环之后,我有另一个更新来确定从今天开始的当前 52 周高价有多长:
编辑:实际上,以下更新是我的主要问题(也是唯一的问题)。持续时间约+/- 10 分钟。 END_OF_EDIT
UPDATE cind_stocks_daily_rates AS A
CROSS JOIN
(SELECT AA.p_date, AA.symbol,
DATEDIFF(STR_TO_DATE(AA.p_date, "%Y %m %d"),STR_TO_DATE(
(SELECT CCC.p_date
FROM cind_stocks_daily_rates CCC
WHERE CCC.symbol = AA.symbol AND CCC.p_date <= AA.p_date AND CCC.high_price = AA.price_52w_high ORDER BY CCC.p_date DESC LIMIT 1)
, "%Y %m %d")) AS last_high_Date
FROM cind_stocks_daily_rates AA) as B ON B.symbol = A.symbol AND B.p_date = A.p_date
SET A.last_52w_high_age_brutto_days = B.last_high_Date
WHERE A.last_52w_high_age_brutto_days IS NULL;
它可以按需要进行所有操作而不会出错,只是需要花费太多时间。有没有可能加快速度?是否可以在游标内一起设置字段“last_52w_high_age_brutto_days”(游标循环后没有第二次更新)?请问有什么想法可以加快查询速度吗?
【问题讨论】:
-
多少时间才算太多?
-
为什么要跨界加入?
-
Besidaes 所有的 STR_:TO_DATE 都必须计时并且您多次执行,为什么不保存它们正确的 mysql 样式并摆脱所有 taht
-
Edit 问题并完成minimal reproducible example,即为示例数据提供
INSERT语句(粘贴文本,不要使用图像,不要链接到外部网站)和表格文本格式的样本数据的期望结果。 -
"And loop ... through the Cursor" -- 这是您要摆脱的第一件事。 RDBMS 擅长基于集合的操作,但在循环游标方面很糟糕。
标签: mysql window-functions cross-join cursors