2009-12-18 5 views
1

J'ai une petite question à propos d'une condition de sélection.SQL Select Condition Question

J'ai le tableau suivant avec les éléments suivants. Ce que j'ai besoin d'obtenir, c'est l'identifiant de l'objet qui correspond aux deux types.

TypeId ObjectId 
1  10 
2  10 
1  11 

donc je dois obtenir à la fois l'objet 10, car il correspond le type id 1 et 2.

SELECT ObjectId 
FROM Table 
WHERE TypeId = 1 
AND TypeId = 2 

Il est évident que cela ne fonctionne pas parce qu'il ne correspond pas à la fois les conditions de la même ligne. Comment puis-je effectuer cette requête? Notez également que je peux transmettre 2 identifiants de type ou plus pour affiner les résultats.

+0

I devrait noter que il ne va pas y avoir seulement 2 identifiants de type dans la requête. Cela fait partie d'une requête plus grande et le nombre d'ID de type transmis sera de 2 ou plus. J'aurais pensé qu'il y aurait eu une solution plus simple à ce problème car les tables de mappage sont courantes dans les bases de données. – Josh

+0

Indiquer le problème complet avec les entrées et le comportement attendus. Si trois sont dans la requête et qu'il doit correspondre à trois ou quoi? –

+0

Comment passez-vous les ID à la requête? Une seule variable séparée par une virgule ou une table? –

Répondre

1

Ce code a été écrit en pensant à Oracle. Il devrait être assez générale pour d'autres saveurs de SQL

select t1.ObjectId from Table t1 
join Table t2 on t2.TypeId = 2 and t1.ObjectId = t2.ObjectId 
where t1.TypeId = 1; 

Pour ajouter TypeIds supplémentaires, il vous suffit d'ajouter un autre rejoindre:

select t1.ObjectId from Table t1 
join Table t2 on t2.TypeId = 2 and t1.ObjectId = t2.ObjectId 
join Table t3 on t3.TypeId = 3 and t1.ObjectId = t3.ObjectId 
join Table t4 on t4.TypeId = 4 and t1.ObjectId = t4.ObjectId 
where t1.TypeId = 1; 

Remarque importante: lorsque vous ajoutez plusieurs jointures, la performance souffrira LOT.

En ce qui concerne la réponse de Bill vous pouvez changer à ce qui suit pour se débarrasser de la nécessité d'assurer l'unicité:

SELECT ObjectId 
FROM (SELECT distinct ObjectId, TypeId from Table) 
WHERE TypeId IN (1, 2) 
GROUP BY ObjectId 
HAVING COUNT(*) = 2; 

Sa façon de le faire échelles mieux que le nombre de types devient plus grande.

+0

Vous aurez besoin d'un préfixe sur l'ObjectId –

+0

Oui, je l'ai réalisé après l'avoir posté. J'ai édité cela, et ai corrigé la clause de joint cassée. –

5

autojointure:

SELECT t1.ObjectId 
FROM Table AS t1 
INNER JOIN Table AS t2 
    ON t1.ObjectId = t2.ObjectId 
    AND t1.TypeId = 1 
    AND t2.TypeId = 2 

Notez que la façon dont vous voulez que le comportement à travailler lors du passage des valeurs, mais c'est un début.

+0

Que faire si j'ai besoin d'ajouter un autre identifiant de type à la requête? – Josh

+0

'Ajouter un autre identifiant de type' Avez-vous besoin de faire correspondre les trois, ou seulement deux des trois? –

+0

Il doit correspondre à tous les ID de type transmis. Donc si je veux filtrer par 2, j'obtiendrai les id d'objet qui correspondent aux deux types d'identification. Si je veux filtrer par 3 identifiants de type, j'obtiendrai les id d'objet qui correspondent aux 3 identifiants de type. – Josh

3

J'ai repoussé la réponse de @Cade Roux, et c'est comme ça que je le ferais.

Mais FWIW, voici une solution alternative:

SELECT ObjectId 
FROM Table 
WHERE TypeId IN (1, 2) 
GROUP BY ObjectId 
HAVING COUNT(*) = 2; 

unique sur TypeId En supposant, ObjectId.


Re le commentaire de @Josh qu'il peut être nécessaire de rechercher trois ou plus TypeId valeurs:

La solution à l'aide JOIN nécessite une jointure par valeur que vous recherchez. La solution ci-dessus utilisant GROUP BY peut être plus facile si vous vous trouvez chercher un nombre croissant de valeurs.

+0

Cela échouera si elle est jamais dans leur avec le même TypeId plus d'une fois. –

+0

@David: Bien, c'est pourquoi j'ai noté que je suppose l'unicité sur TypeId, ObjectId. –

+1

Cela peut être préférable à ma réponse (pour la maintenance et la performance) avec l'exigence des listes de variables (revoir le plan d'exécution, bien sûr), mais échouera également dans le cas de 3 correspondances. Je pense que l'exigence d'une contribution variable doit être mieux définie pour comprendre une solution finale appropriée. –

0

Essayer cette

Exemple d'entrée: (cas 1)

declare @t table(Typeid int,ObjectId int) 
insert into @t 
    select 1,10 union all select 2,10 union all  
    select 1,11 
select * from @t 

Exemple d'entrée: (Cas 2)

declare @t table(Typeid int,ObjectId int) 
insert into @t 
    select 1,10 union all select 2,10 union all 
    select 3,10 union all select 4,10 union all 
    select 5,10 union all select 6,10 union all 
    select 1,11 union all select 2,11 union all 
    select 3,11 union all select 4,11 union all 
    select 5,11 union all select 1,12 union all 
    select 2,12 union all select 3,12 union all 
    select 4,12 union all select 5,12 union all 
    select 6,12 
select * from @t 

Exemple d'entrée: (Cas 3) [Les entrées en double sont là]

declare @t table(Typeid int,ObjectId int) 
insert into @t 
    select 1,10 union all select 2,10 union all 
    select 1,10 union all select 2,10 union all 
    select 3,10 union all select 4,10 union all 
    select 5,10 union all select 6,10 union all 
    select 1,11 union all select 2,11 union all 
    select 3,11 union all select 4,11 union all 
    select 5,11 union all select 1,12 union all 
    select 2,12 union all select 3,12 union all 
    select 4,12 union all select 5,12 union all 
    select 6,12 union all select 3,12 

pour le cas 1, la sortie doit être 10

Pour le cas 2 & 3, la sortie doit être de 10 et 12

Query:

select X.ObjectId from 
(
select 
      T.ObjectId 
      ,count(ObjectId) cnt 
from(select distinct ObjectId,Typeid from @t)T 
where T.Typeid in(select Typeid from @t) 
group by T.ObjectId)X 
join (select max(Typeid) maxcnt from @t)Y 
on X.cnt = Y.maxcnt