2012-09-27 1 views
5

Celui-ci m'a laissé bouche bée depuis quelques heures et à ce stade, je pense que je besoin d'aide ...groupe par colonne A, mais la colonne B comparant

je dois comparer plusieurs groupes à partir d'une seule table et pour identifier où les éléments répertoriés dans la col B correspondent. Par exemple: -

Col A...............Col B 
John................Apple 
John................Orange 
John................Banana 
Mary................Orange 
Mary................Strawberry 
David...............Apple 
David...............Orange 
David...............Banana 

Je souhaite que 'John' et 'David' soient renvoyés car leurs éléments de la colonne B correspondent. J'espère que cela a du sens! Merci d'avance! G

+2

quelle version de sql-server? – Taryn

+0

SQL Server 2008 Express – user1704276

+0

Il est utile que la sortie attendue soit définie de manière très explicite. Vous avez un exemple d'entrée ci-dessus. Essayez d'écrire un exemple de sortie dans le format exact que vous souhaitez. –

Répondre

6

Voici la SQL Fiddle pour cette solution, afin que vous puissiez jouer avec vous-même.

select A.ColA Person1, B.ColA Person2 
    from (select ColA, count(ColB) CountBs 
      from tbl 
      group by ColA) G1 
    join (select ColA, count(ColB) CountBs 
      from tbl 
      group by ColA) G2 on G1.ColA < G2.ColA 
          and G1.CountBs = G2.CountBs 
    join tbl A on A.ColA = G1.ColA 
    join tbl B on B.ColA = G2.ColA and A.ColB = B.ColB 
group by A.ColA, B.ColA, G1.CountBs 
having count(distinct A.ColB) = G1.CountBs 

-- subqueries G1 and G2 are the same and count the expected colB's per colA 
-- G1 and G2 are joined together to get the candidate matches 
-- of ColA with the same number of ColB's 
-- we then use G1 and G2 to join into tbl, and further join 
-- between A and B where the ColB's match 
-- finally, we count the matches between A and B and make sure the counts match 
-- the expected count of B's for the pairing 
+0

excellente solution! – RomanKonz

+0

si vous ajoutez ces enregistrements: Tim .... Apple Jim .... Orange Jim .... Banane Il ajoute Jim à l'ensemble de retour. – jTC

+1

@JTC Merci. fixé maintenant. C'est l'examen par les pairs pour vous :) – RichardTheKiwi

0

Toutes les personnes qui ont un élément dans la colonne b qui correspond à plus que sur la personne (je suppose que vous cherchez peut-être plus que seulement 2 matchs?):

SELECT tableName.ColA, tableName.ColB 
FROM (SELECT ColB 
    FROM tableName 
    GROUP BY ColB 
    HAVING COUNT(1) > 1) fruits 
INNER JOIN tableName ON fruits.ColB = tableName.ColB 
ORDER BY tableName.ColB, tableName.ColA 
0

ColA1 correspond à ColA2 si:
Count (ColA1) = Count (ColA2) = Count (ColA1 x ColA2)

Cette approche tente d'optimiser la vitesse de requête.

Matérialiser le nombre brut car il est utilisé plusieurs fois et peut déclarer un PK.
(un CTE est juste la syntaxe et est évalué)

L'où RA.rawcount = RB.rawcount permet seulement d'évaluer la jointure si les comptes sont égaux. Et le plan de requête indique qu'il est exécuté en premier.

create table #rawcount 
(ColA varchar(50) not null primary key, rawcount int not null) 
insert into #rawcount 
select [ColA], COUNT(*) as [rawCount] 
from  [tbl] 
group by [ColA] 
order by [ColA] 

select a.ColA as ColA1, b.ColA as ColA2, COUNT(*) [matchcount] 
from tbl A 
join tbl B 
on a.ColB = b.ColB 
and a.ColA < b.ColA 
join #rawcount RA 
on RA.ColA = A.ColA 
join #rawcount RB 
on RB.ColA = B.ColA 
where RA.rawcount = RB.rawcount -- only evaluate if count same 
group by a.ColA, b.ColA, RA.rawcount 
having COUNT(*) = RA.rawcount 
Questions connexes