web-dev-qa-db-fra.com

Joindre une liste de valeurs avec des lignes de table en SQL

Supposons que j'ai une liste de valeurs, telle que 1, 2, 3, 4, 5 et une table dans laquelle certaines de ces valeurs existent dans une colonne. Voici un exemple:

id  name
 1  Alice
 3  Cindy
 5  Elmore
 6  Felix

Je souhaite créer une instruction SELECT qui inclura toutes les valeurs de ma liste ainsi que les informations des lignes correspondant à ces valeurs, c.-à-d., Effectue un LEFT OUTER JOIN entre ma liste et la table.

id  name
 1  Alice
 2  (null)
 3  Cindy
 4  (null)
 5  Elmore

Comment faire cela sans créer une table temporaire ni utiliser plusieurs opérateurs UNION?

19
uncoder

Si vous utilisez Microsoft SQL Server 2008 ou une version ultérieure, vous pouvez utiliser Table Value Constructor

 Select v.valueId, m.name 
 From (values (1), (2), (3), (4), (5)) v(valueId)
     left Join otherTable m
        on m.id = v.valueId

Je ne sais pas si Oracle a une construction similaire

34
Charles Bretana

la solution suivante pour Oracle est adoptée à partir de this source . L'idée de base est d'exploiter les requêtes hiérarchiques d'Oracle. vous devez spécifier une longueur maximale de la liste (100 dans l'exemple de requête ci-dessous).

   select d.lstid
        , t.name
     from (
               select substr(
                           csv
                         , instr(csv,',',1,lev) + 1
                         , instr(csv,',',1,lev+1 )-instr(csv,',',1,lev)-1
                      )  lstid
                 from (select ','||'1,2,3,4,5'||',' csv from dual)
                    , (select level lev from dual connect by level <= 100)
                where lev <= length(csv)-length(replace(csv,','))-1         
          ) d
left join test  t on ( d.lstid = t.id )
        ;

découvrez ce violon sql pour le voir fonctionner.

4
collapsar

Un peu tard, mais pour Oracle, vous pourriez faire quelque chose comme ceci pour obtenir un tableau de valeurs:

SELECT rownum + 5 /*start*/ - 1 as myval
FROM dual
CONNECT BY LEVEL <= 100 /*end*/ - 5 /*start*/ + 1

... Et ensuite, joignez ça à votre table:

SELECT *
FROM
(SELECT rownum + 1 /*start*/ - 1 myval
FROM dual
CONNECT BY LEVEL <= 5 /*end*/ - 1 /*start*/ + 1) mypseudotable
left outer join myothertable
    on mypseudotable.myval = myothertable.correspondingval
2
EdmCoff

En supposant que myTable soit le nom de votre table, le code suivant devrait fonctionner.

;with x as 
(
  select top (select max(id) from [myTable]) number from [master]..spt_values
),
y as
(select row_number() over (order by x.number) as id
from x)
select y.id,  t.name
from y left join myTable as t
on y.id = t.id;

Attention: Ceci est une implémentation de SQL Server.

violon

1
user353gre3

Supposons que votre table ayant les valeurs 1,2,3,4,5 s'appelle list_of_values et que la table contenant certaines valeurs, mais que la colonne de nom s'appelle some_values, vous pouvez procéder comme suit:

SELECT B.id,A.name
FROM [list_of_values] AS B
LEFT JOIN [some_values] AS A
ON B.ID = A.ID
0
xbb

Pour obtenir les numéros séquentiels requis pour une partie de la sortie (cette méthode élimine les valeurs à saisir pour n nombres):

declare @site as int
set @site = 1
while @site<=200
begin
insert into ##table
values (@site)

set @site=@site+1
end

Résultat final [étape ci-dessus]: 

select * from ##table
select v.id,m.name from  ##table  as v
left outer join [source_table] m
 on m.id=v.id
0
Amarnadh