2013-02-28 125 views
2

運行SQL Server的2005/2008,我重寫我的查詢是更清潔,更符合不包括壞習慣。我曾經有很多IF陳述和PIVOT這樣做,但找到了一個更好的方式來實現它,只需要最後一點,使其幾乎完美。INSERT INTO動態添加列

DECLARE @startdate DATETIME; 
DECLARE @enddate DATETIME; 
DECLARE @showstore INT; 
DECLARE @showcashier INT; 
DECLARE @showregister INT; 
DECLARE @showdate INT; 
DECLARE @sql NVARCHAR(MAX); 
DECLARE @result0 NVARCHAR(MAX); 

SET @startdate = '1/1/2012'; 
SET @enddate = '2/28/2013'; 
SET @showdate = 1; 
SET @showstore = 0; 
SET @showcashier = 1; 
SET @showregister = 0; 
SET @startdate = DATEADD(DAY, DATEDIFF(DAY, 0, @startdate), 0); 
SET @enddate = DATEADD(DAY, DATEDIFF(DAY, 0, @enddate), 0); 

SET @sql = N'CREATE TABLE ##a13 (' + SUBSTRING(
CASE WHEN @showdate = 1 THEN ',[Transaction Date] DATETIME' ELSE '' END + 
CASE WHEN @showstore = 1 THEN ',[Store ID] VARCHAR(10)' ELSE '' END + 
CASE WHEN @showcashier = 1 THEN ',[Cashier] VARCHAR(100)' ELSE '' END + 
CASE WHEN @showregister = 1 THEN ',[Register] VARCHAR(20)' ELSE '' END, 2, 2000); 

DECLARE myCursor CURSOR FOR 
    SELECT DISTINCT c.CurrencyDesc 
    FROM dbo.Currencies AS c INNER JOIN dbo.rpPay AS p ON c.POSCurrency = p.PayType 
     INNER JOIN dbo.RPTrs AS r ON r.ReceiptNO = p.ReceiptNo 
    WHERE 
     c.CurrencyDesc <> 'Testing' AND c.CurrencyDesc <> 'Cash Change' AND 
     r.TRSDate >= @startdate AND r.TRSDate <= @enddate 
OPEN myCursor 
FETCH NEXT FROM myCursor INTO @result0 
WHILE @@FETCH_STATUS = 0 
    BEGIN 
     SET @sql = @sql + ',[' + @result0 + '] INT' 
     FETCH NEXT FROM myCursor INTO @result0 
    END 
CLOSE myCursor 
DEALLOCATE myCursor 

SET @sql = @sql + ')' 
EXECUTE sp_executesql @sql, N'@startdate DATETIME, 
    @enddate DATETIME',@startdate, @enddate; 

SET @sql = 'SELECT * FROM ##a13; DROP TABLE ##a13' 
EXECUTE sp_executesql @sql 

返回一個空行的表。 (知道貨幣表有更多CurrencyDesc然後在這裏顯示,因爲這些都只是在提供的日期範圍內所使用的那些)

enter image description here

這正是我從它的期望。迄今爲止非常棒。現在我需要根據日期範圍(@startdate >= and <= @enddate)向其添加數據行,並取決於他們從4種可能的選項中檢查了什麼(@showstore, @showcashier, @showdate, @showregister

示例:日期從2013年1月1日到2 /只有(如被看見在圖片)二千零十三分之二十八並顯示註冊應該有這樣的數據:

| Register | Cash | House Acct | MasterCard | Visa/MC 
-------------------------------------------------------- 
1 | 01  | 20.00 | 235.25  | 1235.32 | 135.23 
2 | 02  | 30.00 | 3542.42 | 323.52  | 523.64 
3 | 03  | 23.35 | 100.32  | 3267.24 | 235.25 

原因2005/2008是因爲一些,這是對執行的客戶,仍然使用2005年才能使用PIVOT我將不得不更改爲2005年

PS每個數據庫的兼容級別。在我得到的又喊道,如果我用#A13,而不是全球## A13的它給了我

Msg 208, Level 16, State 0, Line 1 
Invalid object name '#a13'. 

我可以做的,所以我不使用全局臨時表?

+0

「原因2005/2008是因爲一些,這是對執行的客戶,仍然使用2005年爲了使用PIVOT我將不得不更改爲2005年每個數據庫的兼容級別」咦? – swasheck 2013-02-28 19:42:38

+0

那麼你問如何不使用'## GLOBAL'臨時表? – JNK 2013-02-28 19:42:45

+1

我對你有關'pivot'的評論感到困惑,兩個sql server 2005/2008都有這個功能。 – Taryn 2013-02-28 19:43:42

回答

6

如果我在這裏不正確,請澄清。

我相信你是問如何填充根據用戶輸入動態列的表。 這裏的答案是,不這樣做!

這種事情的最佳實踐是在輸出表中包含所有字段,然後在應用程序/顯示層中只顯示用戶請求的字段。

自定義內TSQL表佈局只是爲了讓一個乾淨的演示介紹了很多不必要的複雜性。這種複雜性也伴隨着性能成本的增加。

如果你有一個靜態輸出表,則是微不足道的返回使用給出的參數數據。

+0

謝謝,我會這樣做。這樣做更有意義。 – JohnZ 2013-02-28 19:54:39

+0

@JohnZ樂於幫忙。請始終記住,數據層不必與用戶看到的內容相匹配,並且在數據庫之外執行此類事情要容易得多。 – JNK 2013-02-28 19:56:40

+0

現在怎麼樣全球臨時表的事情?我如何使用動態SQL臨時表而不使用全局變量? – JohnZ 2013-02-28 20:03:24