1

2 つの列を含むテーブルがあります

ID | Name
----------------
1  | John
2  | Sam
3  | Peter
6  | Mike

ID が欠落しています。この場合、これらは45です。

それらを見つけて、ランダムな名前と一緒にこのテーブルに挿入するにはどうすればよいですか?

更新: カーソルと一時テーブルは許可されていません。ランダムな名前は、'Name_' + 乱数である必要があります。'Abby' のように指定された値になるかもしれません。だから関係ない。

4

5 に答える 5

4

再帰CTEを使用すると、次のように欠落しているIDを特定できます。

DECLARE @Table TABLE(
        ID INT,
        Name VARCHAR(10)
)

INSERT INTO @Table VALUES (1, 'John'),(2, 'Sam'),(3,'Peter'),(6, 'Mike')

DECLARE @StartID INT,
        @EndID INT

SELECT  @StartID = MIN(ID),
        @EndID = MAX(ID)
FROM    @Table

;WITH IDS AS (
        SELECT  @StartID IDEntry
        UNION ALL
        SELECT  IDEntry + 1
        FROM    IDS
        WHERE   IDEntry + 1 <= @EndID
)
SELECT  IDS.IDEntry [ID]
FROM    IDS LEFT JOIN
        @Table t    ON  IDS.IDEntry = t.ID
WHERE   t.ID IS NULL
OPTION (MAXRECURSION 0)

このオプションMAXRECURSION 0を使用すると、コードでSQLSERVERの再帰制限を回避できます。

クエリヒントおよびWITHcommon_table_expression(Transact-SQL)から

MAXRECURSIONnumberこのクエリで許可される再帰の最大数を指定します。numberは、0から32767までの非負の整数です。0が指定されている場合、制限は適用されません。このオプションが指定されていない場合、サーバーのデフォルトの制限は100です。

クエリの実行中にMAXRECURSION制限の指定された数またはデフォルトの数に達すると、クエリは終了し、エラーが返されます。

このエラーのため、ステートメントのすべての効果がロールバックされます。ステートメントがSELECTステートメントの場合、部分的な結果が返されるか、結果が返されない場合があります。返される部分的な結果には、指定された最大再帰レベルを超える再帰レベルのすべての行が含まれない場合があります。

RANDOM名の生成は、そのような名前の要件、およびそのような名前の列タイプの影響を大きく受けます。このランダムな名前は正確には何を意味しますか?

于 2012-04-11T18:17:47.387 に答える
3

これは、再帰的な Common Table Expression CTE を使用して行うことができます。方法の例を次に示します。

DECLARE @MaxId INT
SELECT @MaxId = MAX(ID) from MyTable
;WITH Numbers(Number) AS 
(
    SELECT 1
    UNION ALL
    SELECT Number + 1 FROM Numbers WHERE Number < @MaxId 
)
SELECT n.Number, 'Random Name'
FROM Numbers n
LEFT OUTER JOIN MyTable t ON n.Number=t.ID
WHERE t.ID IS NULL

共通テーブル式の使用と共通テーブル式使用した再帰クエリに役立つ CTE に関する記事をいくつか紹介します。

于 2012-04-11T18:22:20.213 に答える
2

再帰CTEの方が高速になるため、より良いソリューションだと思いますが、私にとっては次のように機能しました。

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TestTable]') AND type in (N'U'))
DROP TABLE [dbo].[TestTable]
GO

CREATE TABLE [dbo].[TestTable](
    [Id] [int] NOT NULL,
    [Name] [varchar](50) NOT NULL,
 CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
))

GO

INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (1, 'John')
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (2, 'Sam')
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (3, 'Peter')
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (6, 'Mike')
GO

declare @mod int
select @mod = MAX(number)+1 from master..spt_values where [type] = 'P'

INSERT INTO [dbo].[TestTable]
SELECT y.Id,'Name_' + cast(newid() as varchar(45)) Name from
(
    SELECT TOP (select MAX(Id) from [dbo].[TestTable]) x.Id from
    (
        SELECT 
        t1.number*@mod + t2.number Id
        FROM master..spt_values t1
        CROSS JOIN master..spt_values t2
        WHERE t1.[type] = 'P' and t2.[type] = 'P'
    ) x
    WHERE x.Id > 0 
    ORDER BY x.Id
) y
LEFT JOIN [dbo].[TestTable] on [TestTable].Id = y.Id
where [TestTable].Id IS NULL
GO

select * from [dbo].[TestTable]
order by Id
GO

http://www.sqlfiddle.com/#!3/46c7b/18

于 2012-04-11T19:56:11.783 に答える
2

テーブル内の最大数を選択することから始めます (トップ 1 id desc を選択)、または max(id) を選択し、while ループを実行して 1...max から反復します。

ループについては、この記事を参照してください。

反復ごとに、行が存在するかどうかを確認し、存在しない場合は、その ID でテーブルに挿入します。

于 2012-04-11T18:15:20.593 に答える
-2

それは実際には非常に簡単です:

探している範囲内のすべての自然数を含む #All_numbers というテーブルを作成します。

#list はデータを含むテーブルです

select a.num as missing_number ,
       'Random_Name' + convert(varchar, a.num) 
from #All_numbers a left outer join #list l on a.num = l.Id
where l.id is null
于 2012-04-12T05:47:52.577 に答える