2009-12-30 4 views
0

J'ai quatre tables: Customer, CustomerCategory, Limit et LimitCategory. Un client peut être dans plusieurs catégories et une limite peut également avoir plusieurs catégories. J'ai besoin d'écrire une requête qui renverra le nom du client et le montant limite où toutes les catégories de clients correspondent à TOUTES les catégories de limite.Joignez deux tables où tous les enregistrements enfants de la première table correspondent à tous les enregistrements enfants de la deuxième table

Je suppose que ce serait similaire à la réponse here, mais je n'arrive pas à le comprendre. Merci!

Modifier - Voici ce que les tables ressemblent:

tblCustomer 
    customerId 
    name 

tblCustomerCategory 
    customerId 
    categoryId 

tblLimit 
    limitId 
    limit 

tblLimitCategory 
    limitId 
    categoryId 
+0

pouvez-vous montrer le schéma correspondant? merci :) –

+0

modifié pour inclure le schéma. merci – adam0101

+0

dupe de cela? http://stackoverflow.com/questions/1849535/t-sql-how-to-write-query-to-get-records-that-match-all-records-in-a-many-to-man –

Répondre

0

Mis à jour! Félix pour avoir souligné une faille dans ma solution existante (3 ans après que je l'ai posté à l'origine, hehe). Après avoir regardé à nouveau, je pense que cela pourrait être correct. Ici, je reçois (1) les clients et les limites avec les catégories correspondantes, plus le nombre de catégories correspondantes, (2) le nombre de catégories par client, (3) le nombre de catégories par limite, (4) Je puis assurer la nombre de catégories pour le client et les limites est le même que le nombre de correspondances entre les clients et les limites:

UNTESTED!

select 
    matches.name, 
    matches.limit 

from (
    select 
     c.name, 
     c.customerId, 
     l.limit, 
     l.limitId, 
     count(*) over(partition by cc.customerId, lc.limitId) as matchCount 
    from tblCustomer c 
    join tblCustomerCategory cc on c.customerId = cc.customerId 
    join tblLimitCategory lc on cc.categoryId = lc.categoryId 
    join tblLimit l on lc.limitId = l.limitId 
) as matches 

join (
    select 
     cc.customerId, 
     count(*) as categoryCount 
    from tblCustomerCategory cc 
    group by cc.customerId 
) as customerCategories 
on matches.customerId = customerCategories.customerId 

join (
    select 
     lc.limitId, 
     count(*) as categoryCount 
    from tblLimitCategory lc 
    group by lc.limitId 
) as limitCategories 
on matches.limitId = limitCategories.limitId 

where matches.matchCount = customerCategories.categoryCount 
and matches.matchCount = limitCategories.categoryCount 
+1

Adam, je ne pense pas que votre solution Testée soit exactement ce que vous cherchez, car elle peut renvoyer un appariement tant que l'un des enregistrements enfant correspond et que les comptes globaux correspondent. –

+0

@FixCartwright, wow vous avez raison. Je pense que les deux solutions ont ce problème. J'ai mis à jour ma réponse. Merci. – adam0101

-1

Je ne sais pas si cela va fonctionner ou non, juste une pensée que j'avais et je ne peux pas tester, je suis sures theres un meilleur moyen! ne soyez pas trop dur :)

SELECT 
    c.customerId 
, l.limitId 
FROM 
tblCustomer c 
CROSS JOIN 
tblLimit l 
WHERE NOT EXISTS 
(
SELECT 
    lc.limitId 
FROM 
    tblLimitCategory lc 
WHERE 
    lc.limitId = l.id 
EXCEPT 
SELECT 
    cc.categoryId 
FROM 
    tblCustomerCategory cc 
WHERE 
    cc.customerId = l.id 
) 
+0

merci, mais je ne sais pas ce qui se passerait dans la clause "ON" de la jointure interne. Il n'y a pas de lien entre les clients et les limites autres que les catégories. J'ai mis à jour la question initiale pour inclure les informations sur le schéma. – adam0101

+0

L'a édité à une jointure croisée, comme je l'ai dit, je ne peux pas le tester, mais il semble que cela devrait fonctionner pour moi! J'espère que ça n'a pas besoin d'être efficace! –

+0

Pourquoi customerId doit-il être supérieur à limitId? Pouvez-vous expliquer cette partie? "c.customerId> l.limitId" – adam0101

0

Je PENSE vous cherchez:

SELECT * 
FROM CustomerCategory 
LEFT OUTER JOIN Customer 
    ON CustomerCategory.CustomerId = Customer.Id 
INNER JOIN LimitCategory 
    ON CustomerCategory.CategoryId = LimitCategory.CategoryId 
LEFT OUTER JOIN Limit 
    ON Limit.Id = LimitCategory.LimitId 
+0

Je crois que cela retournera des enregistrements où TOUTES les catégories de clients correspondent aux catégories de limite. J'ai besoin de TOUTES les catégories pour correspondre. Merci quand même. – adam0101

+0

Modifié pour sélectionner TOUTES les CustomerCategories et laisser des zéros là où les clients ou les limites n'existent pas ... c'est ce que vous voulez? –

+0

Non, je crois que cela retournera des enregistrements si, par exemple, une limite a deux des trois catégories d'un client. J'ai besoin que le groupe de catégories du client corresponde exactement au groupe de catégories de la limite. – adam0101

Questions connexes