SQL Server 2008:复杂插入

| 我有一张叫ѭ0的表:
BeginYear  |   EndYear   |    Name
1974           1983           Robert
对于
Employees
中的每条记录,我需要将每年插入到名为
EmployeeYears
的新表中 所以:
For Each Record in Employees
    For i as int = Begin Year to End year
        INSERT i, Name into EmployeeYears
在SQL中执行此操作的任何方法...可能使用游标吗?     
已邀请:
其要旨是使用WITH语句创建所有记录并将其插入到最终表中。
;WITH q AS (
  SELECT Year = BeginYear
         , Name
  FROM   Employees
  UNION ALL
  SELECT q.Year + 1
         , q.Name
  FROM   q
         INNER JOIN Employees e ON e.Name = q.Name
                                   AND e.EndYear > q.Year
)
INSERT INTO EmployeeYears
SELECT * FROM q
OPTION(MAXRECURSION 0)
测试数据
CREATE TABLE Employees (BeginYear INTEGER, EndYear INTEGER, Name VARCHAR(32))
CREATE TABLE EmployeeYears (Year INTEGER, Name VARCHAR(32))

INSERT INTO Employees
  SELECT 1974, 1976, \'Robert\'
  UNION ALL SELECT 1972, 1975, \'Lieven\'
结果
SELECT  *
FROM    EmployeeYears
ORDER BY Name, Year

1972    Lieven
1973    Lieven
1974    Lieven
1975    Lieven
1974    Robert
1975    Robert
1976    Robert
    
如果您有数字表,则可以加入该表以获取各个年份的记录,并避免使用光标。我只是用从1965年到968年的数字填充了数字表,但是一个realife数字表(出于示例目的,它也不会是一个临时表,如下所示,但它存在于您的模式中)可能会有几百万条记录对于很多比较有用。
create table #Numbers (Number int)
insert into #Numbers
select 1965
union
select 1966
union 
select 1967
union 
select 1968

create table #employees (name varchar (50), beginyear int, endyear int)
insert into #employees
select \'Dick\', 1966, 1968
union all 
select \'harry\', 1965, 1967
union all 
select \'tom\', 1955, 1966

insert into EmployeeYears (Name, [Year])
select Name, n.number 
from #Employees e
join #Numbers n on  n.number between e.beginyear and e.endyear
order by name
    
是的,您实际上必须做一个循环...我宁愿不使用CURSORS,但这种情况sorta还是有道理的...无论如何,这里的代码只是一个直接循环,向您展示了您可以做的事情SQL中的这种代码:
DECLARE @Employee VARCHAR(100)
DECLARE @BeginYear INT, @EndYear INT, @i INT

SET @Employee = \'\'

WHILE (1=1)
BEGIN
    SET @Employee = (SELECT TOP 1 Name FROM Employees ORDER BY Name WHERE Name > @Employee)

    IF @Employee IS NULL BREAK

    SELECT @BeginYear = BeginYear, @EndYear = EndYear FROM Employees WHERE Name = @Employee

    SET @i = @BeginYear

    WHILE (@i <= @EndYear)
    BEGIN
        INSERT INTO EmployeeYears (Year, Name) VALUES (@i, @Employee)
        SET @i = @i + 1
    END
END
    
您可以使用递归CTE:
;WITH CTE AS
(
    SELECT BeginYear, EndYear, Name
    FROM Employees
    UNION ALL
    SELECT BeginYear+1, EndYear, Name
    FROM CTE 
    WHERE BeginYear < EndYear
)  
INSERT INTO EmployeeYears (Year, Name)
SELECT BeginYear, Name
FROM CTE 
ORDER BY Name, BeginYear
OPTION(MAXRECURSION 0)
    
您可以使用递归过程。就像一个波纹管:
CREATE Procedure InsertYear
    @Name ....
    @BeginYear ...
    @EndYear ...
AS
{
     INSERT INTO  EmployeeYears  VALUES(@BeginYear, @Name);
     SET  @BeginYear = @BeginYear + 1
     IF @BeginYear < @EndYear
     BEGIN
         InsertYear(@Name, @BeginYear, @EndYear)
     END

     RETURN
}
    
您可以这样做,但是如果Begin或end超过2047,它将失败
INSERT INTO EmployeeYears (number, name)
SELECT v.number, e.name
FROM 
    Employees e
    INNER JOIN master..spt_values v on 
    v.number between beginYear and endYear
    

要回复问题请先登录注册