这可以使用代码轻松完成,但我想知道是否可以使用SQL Server(2008)在数据库级别完成。
我有一张类似于下面的表格:
CROP_ID YEAR_ PRODUCTION
1 1 0
1 2 300
1 3 500
2 1 100
2 2 700
我希望能够针对每种作物类型的 n 年份运行查询重复此操作,例如
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
答案 0 :(得分: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 :(得分: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的倍数等。如果它足够小,在常量表上不需要索引,但这些索引可能对更大的开启有用。
答案 2 :(得分: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
*/
答案 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函数的实用程序。