2010-05-31 4 views
27

En supposant que j'ai une table contenant les informations suivantes:Fusionner deux lignes dans SQL

FK | Field1 | Field2 
===================== 
3 | ABC | *NULL* 
3 | *NULL* | DEF 

est-il un moyen que je peux effectuer une sélection sur la table pour obtenir le

suivant
FK | Field1 | Field2 
===================== 
3 | ABC | DEF 

Merci

Editer: Fixer le nom du champ2 pour plus de clarté

Répondre

5

Il y a plusieurs façons selon certaines données ules que vous n'avez pas inclus, mais voici une façon d'utiliser ce que vous avez donné.

SELECT 
    t1.Field1, 
    t2.Field2 
FROM Table1 t1 
    LEFT JOIN Table1 t2 ON t1.FK = t2.FK AND t2.Field1 IS NULL 

Une autre façon:

SELECT 
    t1.Field1, 
    (SELECT Field2 FROM Table2 t2 WHERE t2.FK = t1.FK AND Field1 IS NULL) AS Field2 
FROM Table1 t1 
2

Il pourrait y avoir des méthodes plus nettes, mais ce qui suit pourrait être une approche:

SELECT t.fk, 
      (
      SELECT t1.Field1 
      FROM `table` t1 
      WHERE t1.fk = t.fk AND t1.Field1 IS NOT NULL 
      LIMIT 1 
     ) Field1, 
      (
      SELECT t2.Field2 
      FROM `table` t2 
      WHERE t2.fk = t.fk AND t2.Field2 IS NOT NULL 
      LIMIT 1 
     ) Field2 
FROM  `table` t 
WHERE  t.fk = 3 
GROUP BY t.fk; 

Test Case:

CREATE TABLE `table` (fk int, Field1 varchar(10), Field2 varchar(10)); 

INSERT INTO `table` VALUES (3, 'ABC', NULL); 
INSERT INTO `table` VALUES (3, NULL, 'DEF'); 
INSERT INTO `table` VALUES (4, 'GHI', NULL); 
INSERT INTO `table` VALUES (4, NULL, 'JKL'); 
INSERT INTO `table` VALUES (5, NULL, 'MNO'); 

Résultat:

+------+--------+--------+ 
| fk | Field1 | Field2 | 
+------+--------+--------+ 
| 3 | ABC | DEF | 
+------+--------+--------+ 
1 row in set (0.01 sec) 

L'exécution de la même requête sans la clause WHERE t.fk = 3, il retournerait le suivant jeu de résultats:

+------+--------+--------+ 
| fk | Field1 | Field2 | 
+------+--------+--------+ 
| 3 | ABC | DEF | 
| 4 | GHI | JKL | 
| 5 | NULL | MNO | 
+------+--------+--------+ 
3 rows in set (0.01 sec) 
11

Les fonctions d'agrégation peuvent vous aider. Les fonctions d'agrégation ne tiennent pas compte NULLs (au moins c'est vrai sur SQL Server, Oracle et Jet/Access), vous pouvez utiliser une requête comme celui-ci (testé sur SQL Server Express 2008 R2):

SELECT 
    FK, 
    MAX(Field1) AS Field1, 
    MAX(Field2) AS Field2 
FROM 
    table1 
GROUP BY 
    FK; 

je MAX, mais tout agrégat qui choisit une valeur parmi les lignes GROUP BY devrait fonctionner.

données de test:

CREATE TABLE table1 (FK int, Field1 varchar(10), Field2 varchar(10)); 

INSERT INTO table1 VALUES (3, 'ABC', NULL); 
INSERT INTO table1 VALUES (3, NULL, 'DEF'); 
INSERT INTO table1 VALUES (4, 'GHI', NULL); 
INSERT INTO table1 VALUES (4, 'JKL', 'MNO'); 
INSERT INTO table1 VALUES (4, NULL, 'PQR'); 

Résultats:

FK Field1 Field2 
-- ------ ------ 
3 ABC  DEF 
4 JKL  PQR 
2

J'ai eu un problème similaire. La différence était que j'avais besoin de beaucoup plus de contrôle sur ce que je retournais donc je me suis retrouvé avec une simple requête claire mais plutôt longue. Voici une version simplifiée basée sur votre exemple.

select main.id, Field1_Q.Field1, Field2_Q.Field2 
from 
(
    select distinct id 
    from Table1 
)as main 
left outer join (
    select id, max(Field1) 
    from Table1 
    where Field1 is not null 
    group by id 
) as Field1_Q on main.id = Field1_Q.id 
left outer join (
    select id, max(Field2) 
    from Table1 
    where Field2 is not null 
    group by id 
) as Field2_Q on main.id = Field2_Q.id 
; 

L'astuce ici est que le premier 'principal' sélectionne les lignes à afficher. Ensuite, vous avez une sélection par domaine. Ce qui est joint doit être toutes les mêmes valeurs renvoyées par la requête 'principale'.

attention, les autres requêtes doivent retourner une seule ligne par id ou vous ignorer les données

1

si une ligne a une valeur dans la colonne champ1 et d'autres lignes ont une valeur nulle alors cette requête pourrait fonctionner.

SELECT 
    FK, 
    MAX(Field1) as Field1, 
    MAX(Field2) as Field2 
FROM 
(
select FK,ISNULL(Field1,'') as Field1,ISNULL(Field2,'') as Field2 from table1 
) 
tbl 
GROUP BY FK