在t-sql的情况下选择别名

时间:2012-03-16 09:56:58

标签: tsql case

我遇到了一个我不确定如何修复的问题。在我的存储过程中,我使用DATEDIFF()函数返回一个日期差异的int。在我的逻辑中,我还从DATEDIFF()的返回值中减去了一个值,它给了我一个负值。这是设计的,因为这个逻辑用于计算费率。

我的问题是我使用的是case语句,但我无法选择列,因为它使用的是Alias。我打算做的是写一些额外的逻辑,如果值为负,我希望它显示为0。

有关详细信息,请参阅下面的代码:

DATEDIFF(d, vso.pod_ata, ISNULL(cncr.cntr_date3, GETUTCDATE())) - 14  AS dem_days, -- Date difference to work out Demurrage days
DATEDIFF(d, cncr.dc_ata, ISNULL(cncr.empty_return_dt, GETUTCDATE())) - 21  AS det_days,

CASE WHEN dem_days <= 0 THEN 0 END AS 'test1',
CASE WHEN det_days <= 0 THEN 0 END AS 'test2',

错误信息是:

列名'dem_days'无效。 列名称'det_days'无效。

解决此问题的最佳解决方案是什么?

4 个答案:

答案 0 :(得分:4)

在您需要时使用此datediff函数。

DATEDIFF(d, vso.pod_ata, ISNULL(cncr.cntr_date3, GETUTCDATE())) - 14  AS dem_days, -- Date difference to work out Demurrage days
DATEDIFF(d, cncr.dc_ata, ISNULL(cncr.empty_return_dt, GETUTCDATE())) - 21  AS det_days,

CASE WHEN DATEDIFF(d, vso.pod_ata, ISNULL(cncr.cntr_date3, GETUTCDATE())) - 14 <= 0 THEN 0 END AS 'test1',
CASE WHEN DATEDIFF(d, cncr.dc_ata, ISNULL(cncr.empty_return_dt, GETUTCDATE())) - 21 <= 0 THEN 0 END AS 'test2',

答案 1 :(得分:1)

您不能在WHERE子句中使用列别名。您需要重复SELECT中的语句:

SELECT
DATEDIFF(d, vso.pod_ata, ISNULL(cncr.cntr_date3, GETUTCDATE())) - 14  AS dem_days, -- Date difference to work out Demurrage days
DATEDIFF(d, cncr.dc_ata, ISNULL(cncr.empty_return_dt, GETUTCDATE())) - 21  AS det_days
FROM Table
WHERE
CASE WHEN DATEDIFF(d, vso.pod_ata, ISNULL(cncr.cntr_date3, GETUTCDATE())) - 14 <= 0 THEN 0 END AS 'test1',
CASE WHEN DATEDIFF(d, cncr.dc_ata, ISNULL(cncr.empty_return_dt, GETUTCDATE())) - 21 <= 0 THEN 0 END AS 'test2'

但是,如果需要将WHERE子句与别名一起使用,则可以按如下方式构造查询:

select *
from 
   (
   select a + b as aliased_column
   from table
   ) dt
where dt.aliased_column = something.

请参阅“Using an Alias column in the where clause in ms-sql 2000

答案 2 :(得分:1)

如果要在SELECT中为select中的其他列或查询的其他部分重用计算,则需要将计算移动到子选择或CTE中。 E.g:

SELECT
    --Useful columns for final result (e.g. other columns from your original query)
    CASE WHEN dem_days <= 0 THEN 0 END AS 'test1',
    CASE WHEN det_days <= 0 THEN 0 END AS 'test2'
FROM
(
    SELECT
         --Other columns (not shown in OPs question)
          DATEDIFF(d, vso.pod_ata, ISNULL(cncr.cntr_date3, GETUTCDATE())) - 14  AS dem_days, -- Date difference to work out Demurrage days
          DATEDIFF(d, cncr.dc_ata, ISNULL(cncr.empty_return_dt, GETUTCDATE())) - 21  AS det_days
    FROM
        --Original Query
) t

最终结束括号后的t只是因为子选择的表 有别名。


如果您根据计算(等)进行计算,那么子选择样式可能会开始看起来有点丑陋/混乱,因此可能首选CTE表单:

;With FirstCalcs as (
     SELECT BaseColumn1,BaseColumn2,CalculatedColumn1,CalculatedColumn2
     FROM ....
), SecondCalcs as (
     SELECT BaseColumn1,BaseColumn2,CalculatedColumn1,CalculatedColumn3 --3 depends on 1 & 2
     FROM FirstCalcs
), ThirdCalcs as (
     SELECT BaseColumn1,BaseColumn2,CalculatedColumn1
     FROM SecondCalcs
     WHERE CalculatedColumn3 = <Condition>
)
SELECT <Final result columns>
FROM ThirdCalcs

至少就是这样,嵌套不会失控。

答案 3 :(得分:0)

这是CROSS APPLY的工作。

SELECT D.dem_days
    , D.det_days
    , T.test1
    , T.test2
FROM cncr
CROSS APPLY (SELECT
    dem_days = DATEDIFF(d, cncr.vso.pod_ata, ISNULL(cncr.cntr_date3, 
               GETUTCDATE())) - 14
    , det_days = DATEDIFF(d, cncr.dc_ata, ISNULL(cncr.empty_return_dt,
                 GETUTCDATE())) - 21
) D
CROSS APPLY (SELECT
    test1 = CASE WHEN D.dem_days <= 0 THEN 0 END
    , test2 = CASE WHEN D.det_days <= 0 THEN 0 END
) T