2010-11-25 7 views
5

Je le tableau suivant:SELECT DISTINCT pour les groupes de données

etc. En d'autres termes, j'ai groupes de données par ID. Vous remarquerez que le groupe de données (A, B) se produit plusieurs fois. Je veux une requête qui permet d'identifier les groupes de données distincts et les numéroter, tels que:

DataID  Data 
101  A 
102  A 
102  B 
103  C 
104  D 

Alors DataID 102 ressemblerait données (A, B), DataID 103 ressemblerait données (C), etc. Pour pour être en mesure de réécrire mon tableau d'origine sous cette forme:

ID DataID 
1 101 
2 102 
3 102 
4 103 
5 104 
6 102 

Comment puis-je faire cela?


PS. Code pour générer la première table:

CREATE TABLE #t1 (id INT, data VARCHAR(10)) 
INSERT INTO #t1 
SELECT 1, 'A' 
UNION ALL SELECT 2, 'A' 
UNION ALL SELECT 2, 'B' 
UNION ALL SELECT 3, 'A' 
UNION ALL SELECT 3, 'B' 
UNION ALL SELECT 4, 'C' 
UNION ALL SELECT 5, 'D' 
UNION ALL SELECT 6, 'A' 
UNION ALL SELECT 6, 'B' 
+0

@littlegreen - Quelle est la base de votre ligne 3 2 dans votre sortie attendue? –

+1

J'ai du mal à voir ce que vous voulez dire. Comment sont liés ID et ID de données (le cas échéant)?Y a-t-il une chance que vous puissiez retravailler l'exemple de sorte qu'il n'y ait pas de valeurs réutilisées entre les tables à moins qu'elles ne se réfèrent à la même chose? –

+0

Parce ID 3 a des données (A, B) dans ma table d'origine, et cette combinaison de données a reçu DataID 2. – thomaspaulb

Répondre

3

À mon avis, vous devez créer un agrégat personnalisé que les données concatène (en cas de cordes approche CLR est recommandée pour des raisons de perf). Ensuite, je voudrais regrouper par ID et sélectionnez distinct du regroupement, en ajoutant une fonction row_number() ou ajouter un dense_rank() votre choix. Quoi qu'il en soit cela devrait ressembler à ceci

with groupings as (
select concat(data) groups 
from Table1 
group by ID 
) 
select groups, rownumber() over() from groupings 
+0

C'est juste ce que j'espérais éviter ... (la concat) – thomaspaulb

+0

Malheureusement c'est probablement la solution. Comment pouvez-vous distinguer différents groupes de données dans l'autre sens que de créer un roi d'agrégat (résumé pour chaque ID) et de le comparer avec d'autres. Pourquoi la solution globale n'est pas viable pour vous. Les chaînes sont-elles longues ou les données sont-elles une sorte de fichier BitMap? – luckyluke

+0

Les chaînes sont assez longues. Je leur ai assigné un ID entier, mais pour concaténer ces entiers dans une chaîne et les distinguer à cet effet semble être un hack moche pour moi. Ce pourrait être la seule solution, mais je voulais vérifier ici avant de l'implémenter. – thomaspaulb

2

La requête suivante utilisant CASE vous donnera le résultat montré ci-dessous. Dès lors, obtenir les groupes de données distincts et continuer plus loin ne devrait pas vraiment être un problème.

SELECT  
    id, 
    MAX(CASE data WHEN 'A' THEN data ELSE '' END) + 
    MAX(CASE data WHEN 'B' THEN data ELSE '' END) + 
    MAX(CASE data WHEN 'C' THEN data ELSE '' END) + 
    MAX(CASE data WHEN 'D' THEN data ELSE '' END) AS DataGroups 
FROM t1 
GROUP BY id 

ID DataGroups 
1 A 
2 AB 
3 AB 
4 C 
5 D 
6 AB 

Cependant, ce genre de logique ne fonctionnera que dans le cas où vous les valeurs « données » sont à la fois fixes et connus à l'avance.

Dans votre cas, vous dites que c'est le cas. Cependant, considérant que vous dites également qu'ils sont 1000 d'entre eux, ce sera franchement, une recherche ridicule à coup sûr :-)

La suggestion de LuckyLuke ci-dessus serait, franchement, être le moyen le plus générique et probablement plus sain à aller à propos de la mise en œuvre de la solution si dans votre cas.

+0

Je suis d'accord. Mais merci pour la réponse :-) – thomaspaulb

0

A partir de vos données d'échantillon (ayant ajouté disparus 2, 'A' tuple, ce qui suit donne les données renuméroté (et uniqueified):

with NonDups as (
select t1.id 
from #t1 t1 left join #t1 t2 
on t1.id > t2.id and t1.data = t2.data 
group by t1.id 
having COUNT(t1.data) > COUNT(t2.data) 
), DataAddedBack as (
    select ID,data 
    from #t1 where id in (select id from NonDups) 
), Renumbered as (
    select DENSE_RANK() OVER (ORDER BY id) as ID,Data from DataAddedBack 
) 
select * from Renumbered 

Giving:

1   A 
2   A 
2   B 
3   C 
4   D 

Je pense alors , c'est une question de division relationnelle pour faire correspondre les lignes de cette sortie avec les lignes de la table d'origine

0

Juste pour partager ma propre solution sale que j'utilise pour le moment:

SELECT DISTINCT t1.id, D.data 
FROM #t1 t1 
CROSS APPLY ( 
    SELECT CAST(Data AS VARCHAR) + ',' 
    FROM #t1 t2 
    WHERE t2.id = t1.id 
    ORDER BY Data ASC 
    FOR XML PATH('')) 
D (Data) 

Et puis en passant analogique à la solution de LuckyLuke.

Questions connexes