0

Слияние двух строк в SQL

1

У меня есть таблица с следующей информацией:

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

Существует ли способ выполнить запрос SELECT к этой таблице, чтобы получить следующий результат:

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

Спасибо!

Редактирование: Исправил название поля Field2 для ясности.

5 ответ(ов)

0

Функции агрегации могут помочь вам в этой ситуации. Функции агрегации игнорируют NULL (по крайней мере, это справедливо для 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
0

Есть несколько способов в зависимости от правил работы с данными, которые вы не указали, но вот один из возможных вариантов, исходя из предоставленной вами информации.

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

Если у вас есть дополнительные условия или специфические требования к данным, пожалуйста, уточните, и я смогу предложить более точное решение.

0

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

SELECT    t.fk,
          (
             SELECT t1.Field1 
             FROM   `table` t1 
             WHERE  t1.fk = t.fk AND t1.Field1 IS NOT NULL
             LIMIT  1
          ) AS Field1,
          (
             SELECT t2.Field2
             FROM   `table` t2 
             WHERE  t2.fk = t.fk AND t2.Field2 IS NOT NULL
             LIMIT  1
          ) AS 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)

Таким образом, приведённый запрос позволяет извлекать ненулевые значения из столбцов Field1 и Field2 для конкретного значения fk, в данном случае — 3, при этом учитываются только существующие ненулевые записи.

0

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

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 
;

Фишка здесь в том, что первый select под названием main выбирает строки для отображения. Затем у вас есть один select для каждого поля. Осуществляемые соединения должны использовать все те же значения, возвращаемые запросом main.

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

0

Если в одной из строк есть значение в столбце 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

В этом запросе мы используем подзапрос для замены значений NULL в полях Field1 и Field2 на пустые строки. Затем, в основном запросе, мы группируем результаты по FK и используем агрегатные функции MAX для получения значений. Таким образом, если в одной из строк в поле Field1 есть значение, оно будет выбрано в результате, даже если в других строках этого значения нет.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь