Объединить две строки в SQL

Предполагая, что у меня есть таблица, содержащая следующую информацию:

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

есть ли способ выполнить выбор в таблице, чтобы получить следующее

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

Спасибо

Изменить: исправить имя field2 для ясности


person Jason    schedule 31.05.2010    source источник


Ответы (7)


Здесь вам могут помочь агрегатные функции. Агрегатные функции игнорируют 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 строк, должен работать.

Данные испытаний:

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
person Cheran Shunmugavel    schedule 31.05.2010

Есть несколько способов, зависящих от некоторых правил данных, которые вы не включили, но вот один из способов, использующий то, что вы дали.

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
person Dustin Laine    schedule 31.05.2010

У меня была похожая проблема. Разница заключалась в том, что мне требовалось гораздо больше контроля над тем, что я возвращал, поэтому в итоге я получил простой понятный, но довольно длинный запрос. Вот упрощенная версия на основе вашего примера.

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 
;

Хитрость здесь в том, что первый выбор «основной» выбирает строки для отображения. Тогда у вас есть один выбор для каждого поля. К тому, к чему присоединяются, должны быть все те же значения, возвращаемые «основным» запросом.

Имейте в виду, что эти другие запросы должны возвращать только одну строку для каждого идентификатора, иначе вы будете игнорировать данные.

person AmaDaden    schedule 07.06.2011

Могут быть более аккуратные методы, но одним из подходов может быть следующее:

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)
person Daniel Vassallo    schedule 31.05.2010

если одна строка имеет значение в столбце field1, а другие строки имеют нулевое значение, этот запрос может работать.

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
person Kamrul Hasan    schedule 08.06.2016

SELECT Q.FK
      ,ISNULL(T1.Field1, T2.Field2) AS Field
FROM (SELECT FK FROM Table1
        UNION
      SELECT FK FROM Table2) AS Q
LEFT JOIN Table1 AS T1 ON T1.FK = Q.FK
LEFT JOIN Table2 AS T2 ON T2.FK = Q.FK

Если есть одна таблица, напишите Table1 вместо Table2

person Smh    schedule 08.06.2020

В моем случае у меня есть такая таблица

---------------------------------------------
|company_name|company_ID|CA        |   WA   |
---------------------------------------------
|Costco      |   1      |NULL      | 2      |
---------------------------------------------
|Costco      |   1      |3         |Null    |
---------------------------------------------

И я хочу, чтобы это было, как показано ниже:

---------------------------------------------
|company_name|company_ID|CA        |   WA   |
---------------------------------------------
|Costco      |   1      |3         | 2      |
---------------------------------------------

Большая часть кода почти такая же:

SELECT
    FK,
    MAX(CA) AS CA,
    MAX(WA) AS WA
FROM
    table1
GROUP BY company_name,company_ID

Единственное отличие состоит в том, что group by, если вы поместите в него два имени столбца, вы можете сгруппировать их попарно.

person Yu Zhao    schedule 05.09.2019