2009-02-10 12 views
3

Je dois transférer des données d'une table à une autre. La deuxième table a une contrainte de clé primaire (et la première n'a aucune contrainte). Ils ont la même structure. Ce que je veux est de sélectionner toutes les lignes du tableau A et l'insérer dans le tableau B sans la ligne en double (si un double IS0 de ligne, je veux seulement prendre le premier que je trouve)SQL - Sélectionne uniquement une ligne non dupliquée

Exemple:

MyField1 (PK) | MyField2 (PK) | MyField3(PK) | MyField4 | MyField5 

---------- 

1    | 'Test'   | 'A1'   | 'Data1' | 'Data1' 
2    | 'Test1'   | 'A2'   | 'Data2' | 'Data2' 
2    | 'Test1'   | 'A2'   | 'Data3' | 'Data3' 
4    | 'Test2'   | 'A3'   | 'Data4' | 'Data4' 

Comme vous pouvez le voir, la deuxième et la troisième ligne ont la même touche pk, mais des données différentes dans MyField4 et MyField5. Donc, dans cet exemple, j'aimerais avoir la première, deuxième et quatrième rangée. Pas le troisième car il s'agit d'une duplication de la seconde (même si MyField4 et MyField5 contiennent des données différentes).

Comment puis-je faire cela avec un seul choix?

thx

+0

MySql, Oracle, MS Sql ou autre chose? – BenMaddox

Répondre

4

D'abord, vous devez définir ce qui rend une ligne "première". Je vais créer une définition arbitraire et vous pouvez changer le SQL comme vous le souhaitez pour ce que vous voulez. Pour cet exemple, je suppose que "first" est la valeur la plus basse pour MyField4 et si elles sont égales, alors la valeur la plus basse pour MyField5. Cela tient également compte de la possibilité que les 5 colonnes soient identiques.

SELECT DISTINCT 
    T1.MyField1, 
    T1.MyField2, 
    T1.MyField3, 
    T1.MyField4, 
    T1.MyField5 
FROM 
    MyTable T1 
LEFT OUTER JOIN MyTable T2 ON 
    T2.MyField1 = T1.MyField1 AND 
    T2.MyField2 = T1.MyField2 AND 
    T2.MyField3 = T1.MyField3 AND 
    (
      T2.MyField4 > T1.MyField4 OR 
      (
       T2.MyField4 = T1.MyField4 AND 
       T2.MyField5 > T1.MyField5 
     ) 
    ) 
WHERE 
    T2.MyField1 IS NULL 

Si vous souhaitez également rendre compte de qui ne sont pas PKs dupliquées dans la table source, mais existe déjà dans votre table de destination, vous devrez expliquer aussi.

2

Quelle est votre base de données? Dans Oracle vous pouvez dire

SELECT FROM your_table 
WHERE rowid in 
(SELECT MIN(rowid) 
FROM your_table 
GROUP BY MyField1, MyField2, MyField3); 

Notez qu'il est quelque peu incertain lequel des rangées avec le même PK sera considéré comme "premier". Si vous devez imposer une commande spécifique, vous devez également trier les autres colonnes.

+0

Est-ce que cela exécutera l'instruction select imbriquée une fois pour chaque ligne dans your_table? Si c'est le cas, alors vous aurez une performance plutôt mauvaise. Heureusement, l'instruction imbriquée serait mise en cache. Pas si familier avec la partie planification de la requête. – Bassam

+0

J'utilise MS SQL 2005 mais je pense que cette syntaxe fonctionnera, j'essaierai demain et je vous le ferai savoir. THX! – Melursus

+0

Il ne serait pas exécuté pour chaque ligne, juste une fois. – Thilo

3

Je ne sais pas comment vous savez que la ligne 2 et la ligne 3 que vous voulez dans la nouvelle table, mais dans une base MySQL, vous pouvez simplement:

insert ignore into new_table (select * from old_table); 

Et le PK ne permettra pas à des entrées en double à insérer.

+0

qui a sauvé ma journée! – trante

0
CREATE TABLE #A(
ID INTEGER IDENTITY, 
[MyField1] [int] NULL, 
[MyField2] [varchar](10) NULL, 
[MyField3] [varchar](10) NULL, 
[MyField4] [varchar](10) NULL, 
[MyField5] [varchar](10) NULL 
) 

INSERT INTO #A (MyField1,MyField2,MyField3,MyField4,MyField5) SELECT * FROM A 

insert into B 
    select MyField1,MyField2,MyField3,MyField4,MyField5 from #A a1 
    where not exists (select id from #A a2 where a2.MyField1 = a1.MyField1 and a2.ID < a1.ID) 

DROP TABLE #A 

OU

insert into b 
    select distinct * from a a1 
    where not exists (
    select a2.MyField1 from a a2 where a1.MyField1 = a2.MyField1 and 
     (a1.MyField2 < a2.MyField2 or a1.MyField3 < a2.MyField3 
     or a1.MyField4 < a2.MyField5 or a1.MyField5 < a2.MyField5)) 
1

Cela dépend de ce que vous cherchez.

Il y a une grande différence entre l'utilisation JOIN + WHERE NULL, NOT IN et NOT EXISTS, y compris le rendement, ce qui est plus important avec des ensembles de données plus importants.

(Voir NOT IN vs. NOT EXISTS vs. LEFT JOIN/IS NULL.)

Les trois méthodes indiquées dans l'article lié sont assez simples.

Questions connexes