2013-08-19 9 views
1

Ici, nous comparons les entrées dans le tableausql comparer les entrées avec différents paramètres

CREATE TABLE a 
(id INT PRIMARY KEY, 
p1 INT, p2 INT, p3 INT, .. , p15 INT) 

p (n) prend la valeur de 0 à 2

Je dois obtenir toutes les entrées avec des combinaisons uniques de parameteres. Ce n'est pas tâche difficile, donc je créé une table comme celui-ci

CREATE TEMPORARY TABLE b AS 
(SELECT 
     t1.id, 
     t2.p1, t2.p2, t2.p3, t2.p4, t2.p5, t2.p6, t2.p7, t2.p8, 
     t2.p9, t2.p10, t2.p11, t2.p12, t2.p13, t2.p14, t2.p15 
FROM 
(
    SELECT 
     p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 
    FROM 
     a 
    GROUP BY 
     p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15 
    HAVING COUNT(*) = 1 
)t2 
LEFT JOIN a t1 on 
t2.p1 = t1.p1 
AND t2.p2 = t1.p2 
AND t2.p3 = t1.p3 
AND t2.p4 = t1.p4 
AND t2.p5 = t1.p5 
AND t2.p6 = t1.p6 
AND t2.p7 = t1.p7 
AND t2.p8 = t1.p8 
AND t2.p9 = t1.p9 
AND t2.p10 = t1.p10 
AND t2.p11 = t1.p11 
AND t2.p12 = t1.p12 
AND t2.p13 = t1.p13 
AND t2.p14 = t1.p14 
AND t2.p15 = t1.p15) 

Ici, nous sommes obtenir enries avec combinaison unique de paramètres.

L'étape suivante consiste pour chaque enregistrement du tableau A à trouver tous les enregistrements de la table B qui diffèrent par un, deux et trois paramètres. Les enregistrements diffèrent par un seul paramètre ne devrait pas être plus d'un, deux enregistrements pour différents paramètres pas plus de deux, etc.

Par exemple:

id | p(n)   
-----+----------------  
1 |000000000000000  
2 |000000000000001 

Je crée une table temporaire de la forme

CREATE TEMPORARY TABLE c AS 
(
SELECT 
    cnt, id1, id2 
FROM 
(
    SELECT 
     (t1.p1 = t2.p1)+(t1.p2 = t2.p2) 
     +(t1.p3 = t2.p3) +(t1.p4 = t2.p4) +(t1.p5 = t2.p5) 
     +(t1.p6 = t2.p6) +(t1.p7 = t2.p7) +(t1.p8 = t2.p8) 
     +(t1.p9 = t2.p9) +(t1.p10 = t2.p10) +(t1.p11 = t2.p11) 
     +(t1.p12 = t2.p12) +(t1.p13 = t2.p13) +(t1.p14 = t2.p14) 
     +(t1.p15 = t2.p15) AS cnt, 
     t1.id id1, 
     t2.id id2 
    FROM 
     b AS t1, 
     a AS t2 
) 
WHERE 
    (cnt BETWEEN 12 AND 14) 
    AND (id1 < id2) 
) 

ici je reçois une table avec des paires qui diffèrent par 1, 2 et 3 paramètres

Mais je suis tombé sur un problème entrées dans la table beaucoup sur 100.000 entrées. Cette table est trop grande (données traitées sur un PC personnel) et la création de la table en donne une très longue. Peut-être que c'est la seule façon d'obtenir tout, mais quelqu'un peut-il avoir une idée de la méthode analytique de résoudre ce problème que les couples de force brute (peut-être pas SQL). Bien sûr, cela sera résolu beaucoup plus rapidement ...

Tout indice sera apprécié! Je vous remercie!

Répondre

1

Si vous voulez une table avec seulement des entrées uniques, vous pouvez créer une seconde table avec toutes les colonnes dans le cadre d'une clé primaire composite:

CREATE TABLE b (
(id INT, p1 INT, p2 INT, p3 INT, .. , p15 INT) 
PRIMARY KEY (p1, p2, p3, .. , p15)) 
IGNORE SELECT * FROM a; 
+0

Pas tout à fait ce que je dois ... Je dois me débarrasser de toutes les entrées qui ont la même combinaison de paramètres et de cette façon ne supprime que les doublons –

0

Peut être ce n'est pas une réponse complète sur votre question, mais si j'ai eu une telle tâche, la première chose que j'essaierais est de généraliser une requête. C'est très difficile pour moi quand je dois spécifier plus de 3 colonnes similaires et c'est très sujet aux erreurs.
Alors, je vous suggère d'essayer de vous faire pivoter des colonnes en lignes et comparer les différences, comme (choisir la méthode pivot que vous voulez, je l'ai juste utilisé pour l'union sqlfiddle, vous pouvez utiliser hstore comme affiché ici PostgreSQL columns to rows with no explicilty specifying column names/columns):

with cte1 as (
    select id, 'p1' as name, p1 as value from a 
    union all 
    select id, 'p2' as name, p2 as value from a 
    union all 
    select id, 'p3' as name, p3 as value from a 
    union all 
    select id, 'p4' as name, p4 as value from a 
), cte2 as (
    select 
     c1.id, sum(case when c1.value = c2.value then 0 else 1 end) as diff 
    from cte1 as c1 
     inner join cte1 as c2 on c2.id <> c1.id and c2.name = c1.name 
    group by c1.id, c2.id 
) 
select 
    id, diff, count(*) as cnt 
from cte2 
group by id, diff 
order by id, diff 

Je suppose que votre table n'a pas de doublons, vous pouvez les éliminer au préalable.

sql fiddle demo

mise à jour
Je ne sais pas si ça va vous aider, bu jeter un oeil à cette question PostgreSQL, find strings differ by n characters, je l'ai demandé à essayer de vous aider, vérifier réponse Erwin Brandstetter Là.

J'ai créé un sql fiddle demo avec différentes méthodes pour vous, il semble que l'utilisation de levenshtein soit la plus rapide, mais elle n'est pas beaucoup plus rapide que votre méthode originale.

+0

Oui, il est une meilleure solution, mais le problème reste le même. Requêtes MySQL pour la deuxième heure (100 000 entrées) –

+0

@AlexanderKhe donc vous travaillez avec MySQL? –

+0

Oui, mais pas nécessairement. J'ai essayé d'utiliser MS SQL Server, mais le résultat était le même –

Questions connexes