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

再帰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 に答える
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 に答える
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 に答える
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 に答える