web-dev-qa-db-ja.com

SQLの2つの行をマージする

次の情報を含むテーブルがあると仮定します。

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

次を取得するためにテーブルで選択を実行する方法はありますか

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

ありがとう

編集:明確にするためにfield2の名前を修正

33
Jason

集計関数が役立つ場合があります。集計関数はNULLsを無視します(少なくともSQL Server、Oracle、およびJet/Accessには当てはまります)。次のようなクエリを使用できます(SQL Server Express 2008 R2でテスト済み)。

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

MAXを使用しましたが、GROUP BY行の中から1つの値を選択するすべての集計が機能します。

テストデータ:

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');

結果:

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

含めていないデータルールに応じていくつかの方法がありますが、ここでは与えたものを使用する1つの方法を示します。

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

別の方法:

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

同様の問題がありました。違いは、返されるものをはるかに制御する必要があるため、単純で明確ではあるがかなり長いクエリになったことです。これはあなたの例に基づいた簡易版です。

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 
;

ここでのコツは、最初に選択した「メイン」で表示する行を選択することです。次に、フィールドごとに1つの選択があります。結合されるのは、「メイン」クエリによって返されるすべての同じ値である必要があります。

これらの他のクエリは、IDごとに1行のみを返す必要があることに注意してください。そうしないと、データが無視されます。

3
AmaDaden

よりきれいな方法があるかもしれませんが、以下は1つのアプローチかもしれません:

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;

テストケース:

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');

結果:

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

WHERE t.fk = 3句なしで同じクエリを実行すると、次の結果セットが返されます。

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

1つの行にfield1列の値があり、他の行にnull値がある場合、このクエリは機能する可能性があります。

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