在 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