2010-12-02 7 views
0

J'ai la nécessité de trouver le prochain numéro disponible dans un ensemble:SQL Tableau croisé dynamique: Sélection du prochain numéro disponible

select min([pivot]) 
from [pivot] 
where not exists (
     select null as nothing 
     from product 
     where product.id = [pivot].[pivot]) 

Cependant, cette application sera utilisée pour un temps très long et le [pivot] champ est un nombre entier. Je ne veux pas vraiment créer 2 147 483 647 [pivot] enregistrements (numéros séquentiels de zéro à un grand nombre dans une table). Créer une vue prend trop de temps.

Y at-il une fonction dans T-SQL (Microsoft SQL Server 2005/2008) qui peut fournir une table [pivot] sans en créer une. La création d'une vue [pivot] est mauvaise car l'accès à la vue prend beaucoup de temps.

+0

cherchez-vous le min (product.id) qui n'existe pas? Donc, si vous aviez 1,3,4 vous voulez qu'il retourne 2? – Beth

Répondre

3

Voyez si quelque chose comme ce travail vous convient. Dans mon exemple, #Test a un trou à 5 qui devrait être retourné, le second (# Test2) n'a pas de trous, donc nous attendons un nouvel ID à retourner. C'est fait en se rejoignant sur soi-même. Je ne sais pas pourquoi vous avez un pivot là-bas, alors je peux mal comprendre votre problème.

CREATE TABLE #test 
(
    num int 
) 

CREATE TABLE #test2 
(
    num int 
) 

INSERT INTO #test (num) 
SELECT 1 UNION ALL 
SELECT 2 UNION ALL 
SELECT 3 UNION ALL 
SELECT 4 UNION ALL 
SELECT 6 UNION ALL 
SELECT 7 

INSERT INTO #test2 (num) 
SELECT 1 UNION ALL 
SELECT 2 UNION ALL 
SELECT 3 UNION ALL 
SELECT 4 UNION ALL 
SELECT 5 UNION ALL 
SELECT 6 UNION ALL 
SELECT 7 

SELECT MIN(t1.num)+1 FROM #test t1 
    LEFT JOIN #test t2 ON t1.num+1 = t2.num 
    WHERE t2.num IS NULL 

SELECT MIN(t1.num)+1 FROM #test2 t1 
    LEFT JOIN #test2 t2 ON t1.num+1 = t2.num 
    WHERE t2.num IS NULL 
+0

J'ai corrigé le SQL. Vous cherchez un moyen de faire fonctionner la table pivotante sans créer une table de 2 milliards d'enregistrements. –

+1

Qu'est-ce qui ne va pas lorsque vous rejoignez l'ensemble des identifiants que vous avez gratuitement (dans le tableau que vous cherchez)? Vous ne pouvez pas créer une table avec 2,1 milliards d'enregistrements gratuitement, à la volée. –

+0

Bonne réponse. Cela a bien fonctionné. J'ai ajouté quelques trucs pour avoir une gamme et toujours fournir une valeur si les jeux étaient vides. –

0
select min([pivot]) + 1 as next_num 

?

+0

J'ai corrigé le SQL. Vous cherchez un moyen de faire fonctionner la table pivotante sans créer une table de 2 milliards d'enregistrements. –

1

Je ne sais pas si c'est le meilleur façon de le faire, mais il répond à la principale question sur la création automatique d'une table:

WITH myValueTable AS (
    SELECT 1 AS 'val' 
    UNION ALL 
    SELECT val + 1 FROM myValueTable WHERE val < 1000 
) 
SELECT * FROM myValueTable OPTION (MAXRECURSION 1000) 

... qui retournera un Table à une seule colonne avec les valeurs 1 à 1000. Toutefois, si vous allez le faire régulièrement, il sera plus rapide (pour la requête globale) de créer une table statique. Si vous pouvez épingler les valeurs à une plage donnée, par exemple, commencer à 124 et générer les 10 prochaines, alors ce serait une amélioration.

Mais sans en savoir plus sur la requête, il est difficile de savoir si c'est la meilleure solution pour vous avec le travail à portée de main. Si vous pouvez fournir des exemples de données sur ce que vous avez et ce que vous voulez faire, cela vous aidera.

... Modifier Si vous essayez de trouver une « lacune » dans un ensemble de nombres, vous pouvez essayer:

WITH mycte AS (
    SELECT product.id, ROW_NUMBER() OVER (ORDER BY product.id) AS 'rownum' FROM product 
    UNION 
    SELECT MAX(product.id), MAX(product.id) + 1 FROM product 
) 
SELECT MIN(rownum) FROM mycte WHERE rownum <> id 

... nouveau ne peut pas garantir la performance cependant, mais peut vous donner des idées pour jouer avec.

+0

C'est très intéressant. Oui, je cherche le prochain numéro inutilisé le plus bas disponible sans générer un tableau croisé dynamique et en prenant le temps zéro pour le découvrir. –