我有一个名为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中执行此操作...可能使用游标?
答案 0 :(得分: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
答案 1 :(得分: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)
<强> TESTDATA 强>
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
答案 2 :(得分:1)
是的,你实际上必须做一个循环...我不想使用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
答案 3 :(得分: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)
答案 4 :(得分: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
}
答案 5 :(得分:0)
您可以这样做但如果开始或结束超过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