2009-09-28 58 views
1

這可以很容易地使用代碼完成,但我想知道是否可以在數據庫級使用SQL Server(2008)完成。使用SQL重複記錄序列

我也有類似的表格下面:

CROP_ID YEAR_ PRODUCTION 
1   1  0 
1   2  300 
1   3  500 
2   1  100 
2   2  700 

我希望能夠運行一個查詢重複此爲ň的年數,每種作物類型如

CROP_ID YEAR_ PRODUCTION 
1  1  0 
1  2  300 
1  3  500 
1  4  0 
1  5  300 
1  6  500 
etc. 

我不確定最好的方法,我認爲我需要一個SP並傳入一年變量,並使用循環結構?然而,確切的語法逃避我。任何幫助讚賞。

更新

對不起,在我原來的職位不提供的所有信息。該表將允許多種作物類型,並且可以更新Produciton值,以便使用固定變量的Case語句不太合適。道歉不清楚。

更新

隨着TVF答案我用下面的修改SQL通過CropType 20年來選擇。

select top 20 b.CROP_ID, 
YEAR_ = n.num * (select count() from MyBaseTable where CROP_ID = 3) + b.YEAR, 
b.PRODUCTION from MyBaseTable b, dbo.fnMakeNRows(20) n 
where CROP_ID = 3 

回答

1

你可以使用,而不是一個存儲過程表值函數,這給多一點靈活性,你的結果做什麼(因爲它可以從直接選擇,插入到另一個表格,加入到其他表格等)。

你也可以通過讓TVF生成N行(每行有0到N-1的數字)來使其更通用,然後使用一些簡單的表達式來生成你需要的列。我發現這樣的TVF在各種情況下都很有用。

如果您需要生成比0..N-1和簡單表達式更復雜的數據,那麼您應該創建一個專用於您的特定需求的TVF。

下面的例子顯示了一個通用的TVF如何可以用來生成你索要數據:

create function fnMakeNRows (@num as integer) 
returns @result table (num integer not null) as 
begin 
if @num is null or @num = 0 
begin 
    return 
end 
declare @n as integer 
set @n = 0 
while @n < @num 
begin 
    insert into @result values (@n) 
    set @n = @n + 1 
end 
return 
end 
go 

select 
CROP_ID = 1, 
YEAR_ = num, 
PRODUCTION = case num % 3 when 0 then 0 when 1 then 300 else 500 end 
from dbo.fnMakeNRows(100000) 

你也可以用它來複制現有錶行(我認爲這更像是你要)。例如,假設base_table包含在你的問題開始的三排,你可以把3行到使用以下60行:

select 
b.CROP_ID, 
YEAR_ = n.num * (select count(*) from base_table) + b.YEAR_, 
b.PRODUCTION 
from base_table b, dbo.fnMakeNRows(20) n 

這(希望)表示通用fnMakeNRows功能的效用。

+0

感謝您的回答。我以前沒有使用過TVF,所以很好試用。第二個Select語句帶回了我需要的結果。現在我只是堅持選擇採取哪種方法! – geographika 2009-09-28 14:10:11

+0

向表中添加第二種作物類型會擾亂年份,所以我修改了該陳述。 TOP關鍵字定義年數,因爲YEAR_ <似乎不工作: select top 20 b.CROP_ID, YEAR_ = n.num *(從MyBaseTable中選擇count(*),其中CROP_ID = 3)+ b.YEAR_, b.PRODUCTION from MyBaseTable b,dbo.fnMakeNRows(20)n 其中CROP_ID = 3 – geographika 2009-09-28 14:30:19

1

一個常見的特技以產生這種數據的,而不需要的存儲過程的是與使用的常數的表。因爲這樣的表可以具有通用性,所以可以根據用途來創建1到100乃至1和1,000之間的所有整數。

對於〔實施例

CREATE TABLE tblConstNums 
(I INT) 
INSERT INTO tblConstNums VALUES (1) 
INSERT INTO tblConstNums VALUES (2) 
INSERT INTO tblConstNums VALUES (3) 
INSERT INTO tblConstNums VALUES (4) 
INSERT INTO tblConstNums VALUES (5) 
-- ... 
INSERT INTO tblConstNums VALUES (1000) 

的溶液可以通過聲明寫入(不需要存儲過程或更一般程序語句:

SELECT CROP_ID, YEAR_ * I, PRODUCTION 
FROM myCropTable T 
JOIN tblConstNums C on 1=1 
WHERE I in (1, 2, 3) 
order by CROP_ID, YEAR_ * I, PRODUCTION 

注意,常數的表可包括用於通常幾列例如,儘管其中許多可以表示爲基本0到n序列中數字的數學表達式,但可以有一列只有偶數,另一個有奇數,另一個有5的倍數等等。如果它足夠小,在一張常量表上不需要索引,但這些可能會對更大的一個有用。

+0

嗨,謝謝你的回答。然而,我從第2年起每年獲得兩項記錄? – geographika 2009-09-28 13:58:41

1

使用這一個:

WITH tn (n) as 
(
    SELECT 0 
    UNION ALL 
    SELECT n+1 
    FROM tn 
    WHERE tn.n < 10 
) 
SELECT DISTINCT t.CROP_ID, t.YEAR_ + (3*tn.n), t.PRODUCTION 
FROM table t, tn 

/*  
    WHERE tn.n < 10 ==> you will get 1 -> (10*3) + 3 = 33 

*/ 
+0

嗨, 我將「FROM表」改爲我的表名 - 這是正確的嗎? 然後運行後,我得到一個「公用表表達式的遞歸成員'噸'具有多個遞歸引用」錯誤時運行查詢。 這是使用SQL Server 2008. – geographika 2009-09-28 13:27:46

+0

是的,將表名替換爲「表」是正確的。 你得到的錯誤是預料之中的,我沒有注意到,因爲我在精神上這樣做,我沒有服務器來測試。我認爲現在沒關係。你可以測試嗎?我已經提出了另一個查詢的情況。 – manji 2009-09-28 13:55:15

+0

嗨, 在沒有計算機的情況下編寫遞歸SQL語句?我印象深刻。 我再次嘗試查詢,並且結果似乎短暫閃爍,然後我收到以下消息: 「語句已終止,最大遞歸2在語句完成前已耗盡。 – geographika 2009-09-28 14:02:51

2

可以在標準的SQL做到這一點,而無需創建一個存儲過程或使用臨時表。下面的例子將爲此做12年。你可以出其擴展爲多少年:

insert into CropYield 
(CropID, Year_, Production) 
Select 1, a.a + (10 * b.a), 
    case (a.a + (10 * b.a)) % 3 
     when 0 then 500 
     when 1 then 0 
     when 2 then 300 
    end 
from (Select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) as a 
cross join (Select 0 as a union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) as b 
where a.a + (10 * b.a) between 1 and 12 
+1

不錯!儘管我可能會保留一個整數表,這樣我可以避免工會。 – dnagirl 2009-09-28 12:57:35

+0

取決於你如何使用它,索引可能比UNION更關注。在我4歲的桌面上,我可以在一秒鐘內生成1,000,000行。對於像我想這個問題一樣的一次性數據加載,創建另一個表可能是不必要的開銷。 – RedFilter 2009-09-28 13:03:32

+0

感謝您的回答。不幸的是,這不會是一個靜態的查詢,因此如果表中的值更新,case語句和模塊化方法將不起作用。 – geographika 2009-09-28 13:40:36