2

我有一张桌子叫Employees

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 中执行此操作的任何方法...可能使用游标?

4

6 回答 6

3

如果您有一个数字表,您可以加入它以获取单个年份记录并避免使用游标。我只是用从 1965 到 968 的数字填充了数字表,但是一个真实的数字表(出于示例目的,它也不是如下所示的临时表,但存在于您的模式中)可能会有几百万条记录对于很多比较很有用。

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
于 2011-04-13T18:59:22.757 回答
3

它的要点是使用 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
于 2011-04-13T19:09:57.863 回答
1

是的,你实际上必须做一个循环......我宁愿不使用 CURSORS,但这种情况有点道理......无论如何,这里的代码只是一个直接循环,向你展示你可以做那种代码在 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
于 2011-04-13T19:06:30.313 回答
1

您可以使用递归 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)
于 2011-04-13T19:18:08.380 回答
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
}
于 2011-04-13T19:13:36.807 回答
0

您可以这样做,但如果 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
于 2011-04-13T19:28:55.490 回答