2015-06-11 44 views
0

我需要一些存儲的特效轉換爲視圖和存儲的特效有很多,其創建得到在隨後的查詢中引用常量DECLARE語句。例如如何在查詢中多次引用SQL代碼片段?

SELECT @FIRSTDAYLASTYEAR = DATEADD(YEAR, DATEDIFF(YEAR, '1901-01-01', DATEADD(YEAR, -1, getdate())), '1901-01-01')

我需要多次指@FIRSTDAYLASTYEAR在一個查詢中,有什麼要做到這一點,而不必聲明變量的最佳方式?

例如考慮:

DECLARE @FIRSTDAYLASTYEAR datetime = DATEADD(YEAR, DATEDIFF(YEAR, '1901-01-01', DATEADD(YEAR, -1, getdate())), '1901-01-01') 
select 
    @FIRSTDAYLASTYEAR as FirstDayLastYear, 
    Case when orderDate > @FIRSTDAYLASTYEAR then 'CurrentOrders' else 'ArchiveOrders' end as State 
from 
    orders 

我不想改寫爲

select 
    DATEADD(YEAR, DATEDIFF(YEAR, '1901-01-01', DATEADD(YEAR, -1, getdate())), '1901-01-01') as FirstDayLastYear, 
    Case when orderDate > DATEADD(YEAR, DATEDIFF(YEAR, '1901-01-01', DATEADD(YEAR, -1, getdate())), '1901-01-01') then 'CurrentOrders' else 'ArchiveOrders' end as State 
from 
    orders 

我希望能夠別名@FIRSTDAYLASTYEAR某種方式查詢。

編輯

感謝您的答覆,你覺得這會執行相同的:

select 
    constants.FirstDayLastYear, 
    Case when orderDate > constants.FirstDayLastYear then 'CurrentOrders' else 'ArchiveOrders' end as State 
from 
    orders o 
cross join 
    (select 
     DATEADD(YEAR, DATEDIFF(YEAR, '1901-01-01', DATEADD(YEAR, -1, getdate())), '1901-01-01') as FirstDayLastYear 
     ) as constants 

原因我問的是,這種代碼可能會被移植到另一個數據庫平臺,在未來某一日期不支持CTE。

+1

@RaduGheorghiu - 因爲意見必須是一個'SELECT'聲明。 –

回答

2

您可以構建一個包含與您的所有變量的單行CTE,然後引用查詢:

WITH Consts as (
    SELECT DATEADD(YEAR, DATEDIFF(YEAR, '19010101', getdate()), '19000101') 
      as FirstDayLastYear, 
      DATEADD(YEAR, DATEDIFF(YEAR, '19010101', getdate()), '190') 
      as LastDayLastYear 
) 
select 
    c.FirstDayLastYear, 
    Case when orderDate > c.FirstDayLastYear then 'CurrentOrders' else 'ArchiveOrders' end as State 
from 
    orders 
     cross join 
    Consts c 

如果你有一個建立在其他變量的頂部變量,你可能需要有多個級別的CTE。

+0

你贏了 - 我只是有點太慢了;-) – cars10m

+0

如果你用'INNER JOIN ON 1 = 1'代替'CROSS JOIN'會不會提高性能? –

+0

@RaduGheorghiu - 不應該有所作爲。 'CROSS JOIN'清楚明確地表明我不想將下一個表與前一個表進行關聯。 –

0

你應該考慮「公用表表達式」像

WITH vars AS (
    SELECT DATEADD(YEAR, DATEDIFF(YEAR, '1901-01-01', DATEADD(YEAR, -1, getdate())), '1901-01-01') as FirstDayLastYear) 
) 
SELECT Case when orderDate > FirstDayLastYear) then 'CurrentOrders' else 'ArchiveOrders' end as State 
... --- your actual select statement for the view ... 
FROM orders, vars 
... 
0

局部變量的觀點在SQL Server中是不允許的。
在您描述的情況下,我可能會創建一個視圖來封裝存儲過程中使用的變量的值,然後將該視圖作爲子查詢或派生表(取決於您的需要)在較大視圖內查詢。

然而,這可能不是將所有的局部變量在存儲過程是可能的。對於不可能的情況,您可以創建一個用戶定義的函數來封裝局部變量的值,並以我使用視圖描述的相同方式使用它。

您可以創建一個cte而不是一個視圖,但是如果您需要相同的邏輯來應用於多個視圖,則必須爲要轉換爲查看的每個過程編寫cte

0

您可以創建一個標量函數:

CREATE FUNCTION fnPrevYear () 
RETURNS date 
AS 
    BEGIN 
     RETURN DATEADD(YEAR, DATEDIFF(YEAR, '1901-01-01', DATEADD(YEAR, -1, GETDATE())), '1901-01-01') 
    END 

並調用需要的地方:

SELECT dbo.fnPrevYear() 

但這將是大數據慢。您可以使用公用表格表達式作爲更好的替代方案。

1

您還可以使用APPLY VALUES

SELECT 
    FirstDateLastYear as FirstDayLastYear, 
    CASE WHEN orderDate > FirstDateLastYear THEN 'CurrentOrders' ELSE 'ArchiveOrders' END AS State 
FROM orders 
CROSS APPLY (VALUES(DATEADD(YEAR, DATEDIFF(YEAR, '1901-01-01', DATEADD(YEAR, -1, getdate())), '1901-01-01'))) AS date(FirstDateLastYear);