2010-11-24 3 views
1

J'ai actuellement 2 tables:Utilisation dans les sous-requêtes SQL

Table Animal: 
animal_id, animal_name owner 

Table Owners 
owner_id owner_name 

Une façon de lister tous les animaux et leurs propriétaires respectifs à utiliser les jointures SQL:

select animal_id, owner_name 
from Animals, Owners 
where (owner = owner_id); 

Je voudrais maintenant savoir comment faire de même avec les sous-requêtes. Je pensais quelque chose comme

select animal_id, owner_name 
from Animals 
where owner_name = (select owner_name from Owners where owner = owner_id) 

mais cela ne semble pas faire l'affaire. Pourquoi?

+3

Une raison pour laquelle vous voulez faire cela? –

Répondre

2

Si vous souhaitez inclure le champ owner_name dans les résultats et que ce champ figure dans la table Owners, vous devez d'une manière ou d'une autre JOINMER les propriétaires dans la requête. La seule chose que vous pouvez renvoyer dans le jeu de résultats sont les colonnes des tables incluses, les constantes ou les valeurs dérivées (en utilisant les fonctions de langage Oracle pour fonctionner sur les colonnes et/ou les valeurs constantes).

Edit:

En fait, maintenant que je pense à ce sujet, vous pouvez utiliser (ou plutôt, essayer - je ne suis pas un utilisateur Oracle) cette syntaxe extrêmement peu performante:

SELECT animal_id, (SELECT owner_name FROM Owners WHERE owner = Animals.owner_id) 
    FROM Animals 

C'est, techniquement, une solution de sous-requête.

+0

Merci! Donc, à partir de vos commentaires, je peux voir qu'il est préférable de faire des jointures au lieu de sous-requêtes? –

+0

Par exemple, si j'ai 10 animaux et 10 propriétaires ne serait-il pas préférable de faire les 10 sous-requêtes que d'avoir à créer une table de 100 éléments? Merci –

+0

La sous-sélection (dans cet exemple, corrélée) est logiquement équivalente à une table LEFT JOIN dans la table OWNERS, car s'il n'y a pas de propriétaire pour l'animal - la valeur du propriétaire serait NULL. La corrélation est généralement ce qui érode les performances, alors que l'optimiseur a été connu pour voir les sous-sélectifs non corrélés comme ayant des plans équivalents aux LEFT JOINs. –

1

Cela ne fonctionne pas car vous avez une colonne 'owner_name' qui n'existe pas dans une table de votre clause from. Pour inclure un résultat sous-requête dans la sélection, inclure la sous requête dans votre clause select:

select animal_id, (select owner_name from Owners where owner = owner_id) 
from Animals 
+0

Merci! N'y a-t-il pas d'autre moyen de ne pas avoir à mettre la sous-requête à cet endroit? Je veux dire, je préférerais (si possible!) Avoir quelque chose de la forme "SELECT a, b, d, d FROM ...." au lieu d'avoir à mettre les sous-requêtes directement sur le "header". –

+0

Je pense que vous faites quelque chose comme: 'select animal_id, owner_name de Animals, (sélectionnez owner_name de Owners où owner = owner_id)'. Le terme général est une table dérivée. Mais en utilisation réelle, vous utiliseriez presque toujours une jointure interne ou externe. – shf301

0

Qu'est-ce que vous utilisez est comme un cartésien jointure implicite.

select animal_id, owner_name 
from Animals, Owners 
where (owner = owner_id); 

Une alternative est jointures

select animal_id, owner_name 
from Animals A inner join Owners O 
    on A.owner = O.owner_id; 

Il semble que vous ne l'aimez pas une sous-requête dans la clause SELECT. Je ne le fais pas non plus. Il ya des choses similaires qui peuvent être faites sans utiliser le mot "JOIN", mais cela est généralement considéré comme le meilleur.

+0

Ce sont deux INNER JOIN équivalents, avec une différence de syntaxe modeste. –

+0

plusieurs tables séparées par des virgules dans FROM fait une jointure interne? J'étais sous l'impression que c'était cartésien, et le WHERE juste filtre des choses après le fait. –

0

Je pense que vous pouvez avoir un défaut de conception: owner ne semble pas être un attribut d'un animal. Au lieu de cela, la propriété peut être une relation entre des animaux et des personnes (ou toute autre entité appartenant à un propriétaire). Par conséquent, vous devriez envisager d'avoir trois tables par ex. Animals (table d'entités), People (ou toute autre table d'entités) et Ownership (une table de relations).

Questions connexes