找到不在SQL数据库表列中的值的最快方法是什么?

时间:2014-03-17 15:44:43

标签: sql sql-server tsql

给定一个SQL Server数据库表Organisation包含smallintiCompanyID(忽略命名约定,它的历史可以追溯到12年)既不是身份也不是索引,但必须是独特;查找表中尚不存在的新值的最快方法是什么?

问题在于我希望这可以保持快速,因为可能值的范围已用完。实际上我不希望使用超过几百个值,所以我的方法中的任何一个都能表现得很好,所以我不会问纯粹的兴趣。

我有两种方法,一种生成一个随机数,然后检查它是否存在于表中;如果不是它尝试另一个。这个方法可能永远不会完成,因为值已用完,所以不是一个好的答案。

DECLARE @companyId SMALLINT
DECLARE @value INT

WHILE @companyId IS NULL OR EXISTS (SELECT 1 FROM dbo.Organisation WHERE iCompanyID = @companyId)
BEGIN
    SET @value = FLOOR(65535 * RAND(DATEPART(mm, GETDATE()) * 100000 + DATEPART(ss, GETDATE()) * 1000 + DATEPART(ms, GETDATE())) + 1)
    IF @value > 32767
        SET @companyId = @value - 65536
    ELSE
        SET @companyId = @value
END

SELECT @companyId [Available ID]

另一种方法基于this answer,并生成所有可能值的列表。这是外连接到表,并返回表中为空匹配的第一个可能值。测试表明,当值用完时,这也变得非常慢,但如果有一个可用值,它至少应该完成。

WITH q AS
(
  SELECT firstId, lastId FROM (SELECT -32768 firstId, 32767 lastId) r
        UNION ALL
  SELECT  firstId + 1, lastId FROM q WHERE firstId < lastId
)
SELECT  TOP 1 q.firstId [Available ID]
FROM    q LEFT JOIN dbo.Organisation o ON q.firstId = o.iCompanyID
WHERE   o.iCompanyID IS NULL
OPTION  (MAXRECURSION 0)

我确信比我自己更聪明的人可以找到一种方法来做到这一点,因为可用值减少并且我有兴趣看到其他可能的方法。

请不要在表格中添加索引;在我感兴趣的当前限制范围内的方法。

1 个答案:

答案 0 :(得分:0)

更简单的方法是使用ROW_NUMBER来查找未使用的第一个索引,但我不知道它是否比您的方法更快。最终,与其他方法一样,它仍然需要对数据进行排序并对其进行迭代,因此除非您能够对这些数据进行索引或非规范化,否则我无法看到大量的性能提升。

SELECT TOP 1 newId FROM 
(
   SELECT newId=(ROW_NUMBER() OVER (ORDER BY iCompanyId)) - 1, iCompanyId FROM Organisation
   GROUP BY iCompanyId
) rownums 
WHERE newId <> iCompanyId