我遇到了一个我不确定如何修复的问题。在我的存储过程中,我使用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'无效。
解决此问题的最佳解决方案是什么?
答案 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