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