Объединить несколько строк с одинаковым идентификатором в одну строку

как я могу объединить несколько строк с одним и тем же ID в одну строку.

когда значение в первой и второй строке в том же столбце одинаково или когда есть значение в первой строке и NULL во втором ряду. Я не хочу сливаться, когда значение в первой и второй строке в одном столбце отличается.

у меня есть таблица:

ID |A    |B    |C
1   NULL  31    NULL
1   412   NULL  1
2   567   38    4
2   567   NULL  NULL
3   2     NULL  NULL
3   5     NULL  NULL
4   6     1     NULL
4   8     NULL  5
4   NULL  NULL  5

Я хочу получить таблицу:

ID |A    |B    |C
1   412   31    1
2   567   38    4
3   2     NULL  NULL
3   5     NULL  NULL
4   6     1     NULL
4   8     NULL  5
4   NULL  NULL  5

3 ответов


Я думаю, что есть более простое решение для приведенных выше ответов (что также правильно). Он в основном получает объединенные значения, которые могут быть объединены в CTE, а затем объединяет их с данными, которые не могут быть объединены.

WITH CTE AS (
    SELECT
        ID,
        MAX(A) AS A,
        MAX(B) AS B,
        MAX(C) AS C
    FROM dbo.Records
    GROUP BY ID
    HAVING MAX(A) = MIN(A)
        AND MAX(B) = MIN(B)
        AND MAX(C) = MIN(C)
)
    SELECT *
    FROM CTE
    UNION ALL
    SELECT *
    FROM dbo.Records
    WHERE ID NOT IN (SELECT ID FROM CTE)

Скрипка SQL:http://www.sqlfiddle.com/#!6/29407/1/0


WITH Collapsed AS (
   SELECT
      ID,
      A = Min(A),
      B = Min(B),
      C = Min(C)
   FROM
      dbo.MyTable
   GROUP BY
      ID
   HAVING
      EXISTS (
         SELECT Min(A), Min(B), Min(C)
         INTERSECT
         SELECT Max(A), Max(B), Max(C)
      )
)
SELECT
   *
FROM
   Collapsed
UNION ALL
SELECT
   *
FROM
   dbo.MyTable T
WHERE
   NOT EXISTS (
      SELECT *
      FROM Collapsed C
      WHERE T.ID = C.ID
);

см. эту работу в скрипке SQL

это работает, создавая все объединяемые строки с помощью Min и Max--который должен быть одинаковым для каждого столбца в ID и что бы исключить NULLs--затем добавление к этому списку всех строк из таблицы, которые не могут быть объединены. Специальный трюк с EXISTS ... INTERSECT учитывает случай, когда столбец имеет все NULL значения ID (и, таким образом,Min и Max are NULL и не равны друг другу). То есть, он функционирует как Min(A) = Max(A) AND Min(B) = Max(B) AND Min(C) = Max(C) а NULLs Для сравнения как равные.

вот немного другое (более раннее) решение, которое я дал, которое может предлагать разные характеристики производительности, и будучи более сложным, мне нравится меньше, но будучи одним текущим запросом (без UNION) мне тоже больше нравится.

WITH Collapsible AS (
   SELECT
      ID
   FROM
      dbo.MyTable
   GROUP BY
      ID
   HAVING
      EXISTS (
         SELECT Min(A), Min(B), Min(C)
         INTERSECT
         SELECT Max(A), Max(B), Max(C)
      )
), Calc AS (
   SELECT
      T.*,
      Grp = Coalesce(C.ID, Row_Number() OVER (PARTITION BY T.ID ORDER BY (SELECT 1)))
   FROM
      dbo.MyTable T
      LEFT JOIN Collapsible C
         ON T.ID = C.ID
)
SELECT
   ID,
   A = Min(A),
   B = Min(B),
   C = Min(C)
FROM
   Calc
GROUP BY
   ID,
   Grp
;

это также В приведенной выше скрипке SQL.

это использует подобную логику как первый запрос для вычисления, должна ли группа быть объединена, а затем использует это для создания ключа группировки, который либо одинаковый для всех строк в ID или отличается для всех строк в ID. С последним Min (Max работал бы так же хорошо) строки, которые должны быть объединены, объединены, потому что они разделяют ключ группировки, а строки, которые не должны быть объединены, не потому, что у них есть отдельные ключи группировки над ID.

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


Вы можете попробовать что-то вроде этого:

select 
isnull(t1.A, t2.A) as A,
isnull(t1.B, t2.B) as B,
isnull(t1.C, t2.C) as C
from
table_name t1
join table_name t2 on t1.ID = t2.ID and ..... 

вы упоминаете понятия первого и второго. Как
вы определяете этот порядок? Поместите этот порядок, определяющий условие
здесь: .....

кроме того, я предполагаю, что у вас есть ровно 2 строки для каждого значения ID.