2009-09-28 85 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