在 SQL Server 2012 中的计算列上使用 CASE
Using CASE on a Calculated Column in SQL Server 2012
我有一个名为 temp 的数据库,其中包含每日股票价格:
Ticker Date price
ABC 01/01/13 100.00
ABC 01/02/13 101.50
ABC 01/03/13 99.80
ABC 01/04/13 95.50
ABC 01/05/13 78.00
XYZ 01/01/13 11.50
XYZ 01/02/13 12.10
XYZ 01/03/13 17.15
XYZ 01/04/13 14.10
XYZ 01/05/13 15.55
我已经计算出每只股票的最高价总计 运行 和每只股票每天的累计价 drawdown
:(最高价 - 当前价格)/最高价)
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1
as Drawdown
FROM [temp] t;
Ticker Date price max_price Drawdown
ABC 01/01/13 100.00 100.00 0.00000
ABC 01/02/13 101.50 101.50 0.00000
ABC 01/03/13 99.80 101.50 -0.01675
ABC 01/04/13 95.50 101.50 -0.05911
ABC 01/05/13 78.00 101.50 -0.23153
XYZ 01/01/13 11.50 11.50 0.00000
XYZ 01/02/13 12.10 12.10 0.00000
XYZ 01/03/13 17.15 17.15 0.00000
XYZ 01/04/13 14.10 17.15 -0.17784
XYZ 01/05/13 15.55 17.15 -0.09329
我现在想创建另一个名为 peak_cnt 的列。
Peak_cnt
将有一个二进制输出:1
如果 drawdown
= 0 和 0 对于其他任何东西。
这是我想要制作的:
Ticker Date price max_price Drawdown Peak_cnt
ABC 01/01/13 100.00 100.00 0.00000 1
ABC 01/02/13 101.50 101.50 0.00000 1
ABC 01/03/13 99.80 101.50 -0.01675 0
ABC 01/04/13 95.50 101.50 -0.05911 0
ABC 01/05/13 78.00 101.50 -0.23153 0
XYZ 01/01/13 11.50 11.50 0.00000 1
XYZ 01/02/13 12.10 12.10 0.00000 1
XYZ 01/03/13 17.15 17.15 0.00000 1
XYZ 01/04/13 14.10 17.15 -0.17784 0
XYZ 01/05/13 15.55 17.15 -0.09329 0
CASE 语句在这里有效吗?我尝试了几个不同版本的 CASE,但都没有成功。这是我用 CASE 得到的最远的结果:
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1 as Drawdown,
CASE WHEN 'Drawdown' < 0 Then 0
ELSE
END as Peak_cnt
FROM [temp] t;
Conversion failed when converting the varchar value 'Drawdown' to data type int.
关于成功使用 CASE 或任何其他解决方案的任何建议?
不,这行不通。
您需要将主查询移动到子查询,并在外部查询(向上一级)中使用引用新 Drawdown
别名的用例表达式:
SELECT x.*,
CASE WHEN Drawdown <> 0 Then 0
ELSE 1
END as Peak_cnt
FROM (
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1 as Drawdown
FROM [temp] t
) x
或者你可以通过这种方式将整个表达式复制到 CASE WHEN ...
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1 as Drawdown,
CASE WHEN (t.price / max(t.price)
over (partition by ticker order by date)) - 1 < 0
Then 0
ELSE 1
END as Peak_cnt
FROM [temp] t;
发生错误的代码部分在这里:
.... CASE WHEN 'Drawdown' < 0 Then 0
ELSE
END as Peak_cnt...
原因是您试图使用 'Drawdown'
引用来指向您在同一个 select
子句中创建的列别名。编译器正在读取相同的代码并尝试将单词 "Drawdown" 与数字“0”进行比较,但无法弄清楚如何进行,因为它尚未处理列别名。
完成您正在寻找的计算的一种方法是通过 sub-query,或通过类似于下面的查询的 CTE。
; with first_query as
(
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1 as Drawdown
FROM [temp] t
)
select a.Ticker
, a.Date
, a.max_price
, a.Drawdown
, case when a.drawdown < 0 then 0 else 1 end as peak_cnt
from first_query as a
我有一个名为 temp 的数据库,其中包含每日股票价格:
Ticker Date price
ABC 01/01/13 100.00
ABC 01/02/13 101.50
ABC 01/03/13 99.80
ABC 01/04/13 95.50
ABC 01/05/13 78.00
XYZ 01/01/13 11.50
XYZ 01/02/13 12.10
XYZ 01/03/13 17.15
XYZ 01/04/13 14.10
XYZ 01/05/13 15.55
我已经计算出每只股票的最高价总计 运行 和每只股票每天的累计价 drawdown
:(最高价 - 当前价格)/最高价)
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1
as Drawdown
FROM [temp] t;
Ticker Date price max_price Drawdown
ABC 01/01/13 100.00 100.00 0.00000
ABC 01/02/13 101.50 101.50 0.00000
ABC 01/03/13 99.80 101.50 -0.01675
ABC 01/04/13 95.50 101.50 -0.05911
ABC 01/05/13 78.00 101.50 -0.23153
XYZ 01/01/13 11.50 11.50 0.00000
XYZ 01/02/13 12.10 12.10 0.00000
XYZ 01/03/13 17.15 17.15 0.00000
XYZ 01/04/13 14.10 17.15 -0.17784
XYZ 01/05/13 15.55 17.15 -0.09329
我现在想创建另一个名为 peak_cnt 的列。
Peak_cnt
将有一个二进制输出:1
如果 drawdown
= 0 和 0 对于其他任何东西。
这是我想要制作的:
Ticker Date price max_price Drawdown Peak_cnt
ABC 01/01/13 100.00 100.00 0.00000 1
ABC 01/02/13 101.50 101.50 0.00000 1
ABC 01/03/13 99.80 101.50 -0.01675 0
ABC 01/04/13 95.50 101.50 -0.05911 0
ABC 01/05/13 78.00 101.50 -0.23153 0
XYZ 01/01/13 11.50 11.50 0.00000 1
XYZ 01/02/13 12.10 12.10 0.00000 1
XYZ 01/03/13 17.15 17.15 0.00000 1
XYZ 01/04/13 14.10 17.15 -0.17784 0
XYZ 01/05/13 15.55 17.15 -0.09329 0
CASE 语句在这里有效吗?我尝试了几个不同版本的 CASE,但都没有成功。这是我用 CASE 得到的最远的结果:
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1 as Drawdown,
CASE WHEN 'Drawdown' < 0 Then 0
ELSE
END as Peak_cnt
FROM [temp] t;
Conversion failed when converting the varchar value 'Drawdown' to data type int.
关于成功使用 CASE 或任何其他解决方案的任何建议?
不,这行不通。
您需要将主查询移动到子查询,并在外部查询(向上一级)中使用引用新 Drawdown
别名的用例表达式:
SELECT x.*,
CASE WHEN Drawdown <> 0 Then 0
ELSE 1
END as Peak_cnt
FROM (
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1 as Drawdown
FROM [temp] t
) x
或者你可以通过这种方式将整个表达式复制到 CASE WHEN ...
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1 as Drawdown,
CASE WHEN (t.price / max(t.price)
over (partition by ticker order by date)) - 1 < 0
Then 0
ELSE 1
END as Peak_cnt
FROM [temp] t;
发生错误的代码部分在这里:
.... CASE WHEN 'Drawdown' < 0 Then 0
ELSE
END as Peak_cnt...
原因是您试图使用 'Drawdown'
引用来指向您在同一个 select
子句中创建的列别名。编译器正在读取相同的代码并尝试将单词 "Drawdown" 与数字“0”进行比较,但无法弄清楚如何进行,因为它尚未处理列别名。
完成您正在寻找的计算的一种方法是通过 sub-query,或通过类似于下面的查询的 CTE。
; with first_query as
(
SELECT t.Ticker,
t.Date,
t.price,
max(t.price) over (partition by ticker order by date) as max_price,
(t.price / max(t.price) over (partition by ticker order by date)) - 1 as Drawdown
FROM [temp] t
)
select a.Ticker
, a.Date
, a.max_price
, a.Drawdown
, case when a.drawdown < 0 then 0 else 1 end as peak_cnt
from first_query as a