Reputation: 111
I've a table Users which has a primary key user_id which is auto incremented when we insert a user_details.Now I've a requirement where in I need to list out all the missing(or deleted) user_ids. I've tried it this way.
DECLARE @NUMBER BIGINT = (SELECT MIN(USER_ID) FROM USERS)
DECLARE @MAX BIGINT = (SELECT MAX(USER_ID) FROM USERS)
CREATE TABLE TEMP_USERS (USER_ID BIGINT)
WHILE @NUMBER <= @MAX
BEGIN
INSERT INTO TEMP_USERS
VALUES(@NUMBER);
SET @NUMBER = @NUMBER+1;
END
SELECT USER_ID from TEMP_USERS
EXCEPT
SELECT USER_ID from USERS
But It's taking too long. Is there an alternate way to increase the performance?
Thanks, Vijay
Upvotes: 0
Views: 57
Reputation: 31249
If you are using MSSQL 2005+. Then you can do this:
DECLARE @NUMBER BIGINT =(SELECT MIN(USER_ID) from USERS)
DECLARE @MAX BIGINT =(SELECT MAX(USER_ID) from USERS)
;WITH Nbrs ( n ) AS (
SELECT @NUMBER UNION ALL
SELECT 1 + n FROM Nbrs WHERE n < @MAX)
SELECT
Nbrs.n AS USERID
FROM
Nbrs
WHERE NOT EXISTS
(
SELECT NULL FROM USERS
WHERE USERS.USER_ID=Nbrs.n
)
OPTION ( MAXRECURSION 0 )
Update
To address the comment. What does MAXRECURSION
do in this case. When we are using a recursive CTE function there is a possiblility that you write it in a way that it never ends. The servers MAXRECURSION
is 100. This can be overridden by using a hint that it should not take the servers MAXRECURSION
.
When we use 0 then it do not have any MAXRECURSION
. If we would not set MAXRECURSION
then after 100 rows it will crash and throw and exception that the MAXRECURSION
has been meet.
Because we can expect that the OP has more the 100 missing user id in the sequence we need to indicate that we want to keep doing the recursion until n < @MAX
Upvotes: 2