如何在 SQL 中添加具有 LAG 的计算列?
How to add calculated column with LAG in SQL?
我有一个 MySQL table(版本 8.0.26)和股票价格,想计算对数价格变化以供将来分析。这是我的 table 和数据。
CREATE TABLE `prices` (
`ticker` varchar(7) NOT NULL,
`date` datetime NOT NULL,
`price` double DEFAULT NULL,
PRIMARY KEY (`ticker`,`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('A', '2021-01-01', '10');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('A', '2021-01-02', '10.1');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('A', '2021-01-03', '11');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('B', '2021-01-01', '50');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('B', '2021-01-02', '51.5');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('B', '2021-01-03', '49');
我可以编写此查询,但该列未保存。
SELECT *, LN(price / lag(price, 1) OVER (PARTITION BY ticker)) AS ln_open_return FROM sandbox.prices;
我将 these 中的这段代码放在一起,但我仍然收到“1064 语法错误:'WITH' 在此位置无效。需要一个表达式。”
ALTER TABLE sandbox.prices
ADD COLUMN ln_change DOUBLE AS (
WITH temp AS (
SELECT
*,
LAG(price, 1) OVER(PARTITION BY ticker ORDER BY date) AS prior
FROM sandbox.prices
)
SELECT
*,
COALESCE(LN(price / prior)) AS ln_change
FROM temp) PERSISTED;
TABLE
(如 CREATE TABLE
或 ALTER TABLE
)中的计算列(又名计算列,又名生成列)不能包含查询,它们只能是从其他派生的表达式列在同一行。
https://dev.mysql.com/doc/refman/8.0/en/create-table-generated-columns.html
- Values of a generated column are computed from an expression included in the column definition.
- Generated column expressions must adhere to the following rules
- [...]
- Subqueries are not permitted.
相反,您可以使用 VIEW
执行此操作。然后您的应用程序代码或报告将查询视图 (prices_with_delta
),而不是基础 table (prices
):
CREATE VIEW sandbox.prices_with_delta AS
SELECT
p2.*,
COALESCE( LN( p2.price / p2.prior ) ) AS ln_change
FROM
(
SELECT
p.*,
LAG( p.price, 1 ) OVER( PARTITION BY p.ticker ORDER BY p.date ) AS prior
FROM
sandbox.prices AS p
) AS p2
我有一个 MySQL table(版本 8.0.26)和股票价格,想计算对数价格变化以供将来分析。这是我的 table 和数据。
CREATE TABLE `prices` (
`ticker` varchar(7) NOT NULL,
`date` datetime NOT NULL,
`price` double DEFAULT NULL,
PRIMARY KEY (`ticker`,`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('A', '2021-01-01', '10');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('A', '2021-01-02', '10.1');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('A', '2021-01-03', '11');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('B', '2021-01-01', '50');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('B', '2021-01-02', '51.5');
INSERT INTO `sandbox`.`prices` (`ticker`, `date`, `price`) VALUES ('B', '2021-01-03', '49');
我可以编写此查询,但该列未保存。
SELECT *, LN(price / lag(price, 1) OVER (PARTITION BY ticker)) AS ln_open_return FROM sandbox.prices;
我将 these
ALTER TABLE sandbox.prices
ADD COLUMN ln_change DOUBLE AS (
WITH temp AS (
SELECT
*,
LAG(price, 1) OVER(PARTITION BY ticker ORDER BY date) AS prior
FROM sandbox.prices
)
SELECT
*,
COALESCE(LN(price / prior)) AS ln_change
FROM temp) PERSISTED;
TABLE
(如 CREATE TABLE
或 ALTER TABLE
)中的计算列(又名计算列,又名生成列)不能包含查询,它们只能是从其他派生的表达式列在同一行。
https://dev.mysql.com/doc/refman/8.0/en/create-table-generated-columns.html
- Values of a generated column are computed from an expression included in the column definition.
- Generated column expressions must adhere to the following rules
- [...]
- Subqueries are not permitted.
相反,您可以使用 VIEW
执行此操作。然后您的应用程序代码或报告将查询视图 (prices_with_delta
),而不是基础 table (prices
):
CREATE VIEW sandbox.prices_with_delta AS
SELECT
p2.*,
COALESCE( LN( p2.price / p2.prior ) ) AS ln_change
FROM
(
SELECT
p.*,
LAG( p.price, 1 ) OVER( PARTITION BY p.ticker ORDER BY p.date ) AS prior
FROM
sandbox.prices AS p
) AS p2