2009-12-03 5 views
0

Comment comparer les groupes de tuples dans sql: Prenons l'exemple suivant:Comment comparer les groupes de tuples dans sql

TABLE T1 
-------- 
GROUP  VALUE 
-----  ----- 
A   FOO 
A   BAR 
X   HHH 
X   ZOO 

TABLE T2 
-------- 
GROUP  VALUE 
-----  ----- 
B   ZOO 
C   FOO 
C   BAR 

Je veux écrire une requête SQL qui compare les groupes de valeurs dans les deux tableaux et rapports les différences. Dans l'exemple illustré, le groupe dans la table a: ((A, FOO), (A, BAR)) est le même que le groupe ((C, FOO), (C, BAR)) même si le nom du groupe est différent . Ce qui compte, c'est que le contenu du groupe soit le même. Enfin la requête rapporterait qu'il y a une différence: c'est le tuple (B, ZOO).

RESULT 
------ 
GROUP  VALUE 
-----  ----- 
B   ZOO 
X   HHH 
X   ZOO 

Bien que le groupe X contenant ZOO en T1 a une valeur correspondant à T2: (B, ZOO), il est toujours pas un match parce que le groupe a également la valeur (X, HHH) qui ne fait pas partie de le (B, ZOO) dans le groupe T2

+0

Quelle devrait être la sortie? Juste une liste de groupes qui sont différents? Ou les différences elles-mêmes? –

+0

La sortie n'est pas vraiment importante, ce qui compte, c'est que la requête voit les groupes et les compare en tant que groupes. – paweloque

+1

Lorsque vous publiez des questions, présentez-nous des exemples de données, des exemples de résultats clairement indiqués et balisés afin que nous puissions facilement vous aider. – JonH

Répondre

1

Quelque chose comme ça

create table t1 (group_id varchar2(20), value varchar2(20)); 
create table t2 (group_id varchar2(20), value varchar2(20)); 

insert into t1 values ('A','FOO'); 
insert into t1 values ('A','BAR'); 
insert into t1 values ('X','HHH'); 
insert into t1 values ('X','ZOO'); 
insert into t2 values ('C','FOO'); 
insert into t2 values ('C','BAR'); 
insert into t2 values ('B','ZOO'); 


select t1.group_id t1_group,t2.group_id t2_group, 
     --t1.all_val, t2.all_val, 
     case when t1.all_val = t2.all_val then 'match' else 'no match' end coll_match 
from 
    (select 'T1' tab_id, group_id, collect(value) all_val, 
      min(value) min_val, max(value) max_val, count(distinct value) cnt_val 
    from t1 group by group_id) t1 
full outer join 
    (select 'T2' tab_id, group_id, collect(value) all_val, 
      min(value) min_val, max(value) max_val, count(distinct value) cnt_val 
    from t2 group by group_id) t2 
on t1.min_val = t2.min_val and t1.max_val = t2.max_val and t1.cnt_val = t2.cnt_val 
/

Je l'ai fait une élimination préliminaire sur la base minmium, maximale et le nombre de valeurs distinctes dans chaque groupe, ce qui aiderait à grands ensembles de données. Si les jeux de données sont suffisamment petits, vous n'en aurez peut-être pas besoin.

Cela vous indique les correspondances. Vous avez juste besoin de pousser une étape supplémentaire pour trouver les groupes qui n'ont aucune correspondance

select t1_group 
from 
(
    select t1.group_id t1_group,t2.group_id t2_group, 
     --t1.all_val, t2.all_val, 
     case when t1.all_val = t2.all_val then 'match' end coll_match 
    from 
    (select 'T1' tab_id, group_id, collect(value) all_val 
    from t1 group by group_id) t1 
    cross join 
    (select 'T2' tab_id, group_id, collect(value) all_val 
    from t2 group by group_id) t2 
) 
group by t1_group 
having min(coll_match) is null 
/

select t2_group 
from 
(
    select t1.group_id t1_group,t2.group_id t2_group, 
     --t1.all_val, t2.all_val, 
     case when t1.all_val = t2.all_val then 'match' end coll_match 
    from 
    (select 'T1' tab_id, group_id, collect(value) all_val 
    from t1 group by group_id) t1 
    cross join 
    (select 'T2' tab_id, group_id, collect(value) all_val 
    from t2 group by group_id) t2 
) 
group by t2_group 
having min(coll_match) is null 
/
+0

Je ne vois pas exactement, comment utilisez-vous les valeurs min/max/count? – paweloque

+0

Si vous avez un grand ensemble de données (dizaines/centaines de milliers de lignes), comparer chaque groupe de la table1 à chaque groupe de la table2 serait une tâche importante. Le nombre min/max/nombre le réduirait à un niveau plus gérable en excluant rapidement les groupes ayant un nombre différent de membres ou avec des valeurs minimum/maximum différentes. –

+0

Que se passe-t-il si les valeurs min/max/count sont les mêmes pour un groupe, mais que les groupes diffèrent? – paweloque

0

différence entre T1 et T2 (deux tables) pourrait être la suivante:

SELECT 
    T1.GROUPNAME, 
    T1.VALUE 
FROM 
    T1 
LEFT JOIN T2 
ON T2.Value = T1.Value 
WHERE T2.GROUPNAME IS NULL 

Par exemple T1 comporte:

Foo 100 BarZZZ 333

Et T2 comprend: Foo 100 Bar 200

Le résultat de cette requête est ZZZ 333 est le seul enregistrement qui ne correspond pas dans les deux tableaux. Vous pouvez même changer le nom du groupe de T2 à dire:

XYZ 100 ZXZ 200

Et le résultat est toujours ZZZ 333. Ceci est par ce que vous demandez, si vous voulez le contraire, vous pouvez soit UNION à elle , ou utilisez RIGHT join.

Jon

+0

En fait, je tiens à ce que les valeurs dans T2 sont des parties du même groupe. – paweloque

+0

Je ne comprends pas ce que vous demandez. Fournissez à nouveau DDL pour toutes vos tables/schémas. Fournir de bons exemples de données et les résultats attendus. Que voulez-vous dire par là que les valeurs de T2 font partie du même groupe? Quelqu'un dans les commentaires vous a posé des questions sur les noms de groupes et vous avez dit que cela n'a pas d'importance pour le nom du groupe, juste que leurs valeurs correspondent dans les deux tableaux. Ma requête gère cela. – JonH