2012-03-16 47 views
1

我碰到過一個我不確定如何解決的問題。在我的存儲過程中,我使用DATEDIFF()函數爲日期差異返回一個int。在我的邏輯中,我還從DATEDIFF()的返回值中減去了一個值,它給了我一個負值。這是設計的,因爲這個邏輯是用來計算費率的。在t-sql的情況下選擇別名

我的問題是我使用的case語句,但我不能選擇列,因爲它使用的是別名。我的目標是做的是寫到哪,如果該值爲負我希望它顯示爲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

只要你需要,就使用這個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', 
+0

完美的工作。我添加了一個else條件,如果它不小於零,它就不會評估它的值。這將向我顯示零或大於零的數字,但同時保持我的費率邏輯完好無損。謝謝你,先生!! – 2012-03-16 10:21:24

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

+0

'HAVING'位表示可疑 - 表達式返回值,而'HAVING'從句只評估謂詞。 – 2012-03-16 10:16:56

+0

@Damien_The_Unbeliever好點,我把它從我的答案中刪除了 – Curt 2012-03-16 10:24:53

1

如果要在您的SELECT中重複使用select中的其他列或查詢的其他部分中的計算,則需要m將計算納入子選擇或CTE中。例如爲:

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 

至少這樣,嵌套不會失控。

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 
相關問題