web-dev-qa-db-fra.com

Fusionner deux lignes dans SQL

En supposant que j'ai un tableau contenant les informations suivantes:

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

est-il possible de faire une sélection sur la table pour obtenir les éléments suivants

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

Merci

Modifier: corriger le nom du champ2 pour plus de clarté

33
Jason

Les fonctions d'agrégation peuvent vous aider ici. Les fonctions d'agrégation ignorent NULLs (du moins, c'est vrai sur SQL Server, Oracle et Jet/Access), vous pouvez donc utiliser une requête comme celle-ci (testée sur SQL Server Express 2008 R2):

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

J'ai utilisé MAX, mais tout agrégat qui choisit une valeur parmi les GROUP BY les lignes devraient 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
16

Il existe plusieurs façons selon certaines règles de données que vous n'avez pas incluses, 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

Autrement:

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

J'avais 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. En 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 la première sélection "principale" sélectionne les lignes à afficher. Ensuite, vous avez une sélection par champ. Ce qui est joint devrait être toutes les mêmes valeurs renvoyées par la requête "principale".

Soyez averti, ces autres requêtes doivent renvoyer une seule ligne par identifiant ou vous ignorerez les données

3
AmaDaden

Il pourrait y avoir des méthodes plus soignées, 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;

Cas de test:

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)

Exécution de la même requête sans le WHERE t.fk = 3, elle renverrait l'ensemble de résultats suivant:

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

si une ligne a une valeur dans la colonne field1 et que les autres lignes ont une valeur nulle, alors cette requête peut 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
1
Kamrul Hasan