T SQL - объединение записей на основе частичной уникальности - PullRequest
0 голосов
/ 28 февраля 2020

Пример данных

DECLARE @T1 TABLE (Id INT, Val1 VARCHAR(20), Val2 VARCHAR(20), [Group] INT);

INSERT INTO @T1
SELECT 1, 'One', '01', 1
UNION
SELECT 2, 'Two', '02', 1
UNION
SELECT 3, 'Three', '03', 1
UNION
SELECT 3, 'Threeeee', '03', 2
UNION
SELECT 4, 'Four', '04', 2
UNION
SELECT 5, 'Five', '05', 2
UNION
SELECT 4, 'Four', '04', 3
UNION
SELECT 5, 'Five', '050', 3
UNION
SELECT 6, 'Six', '06', 3;

В настоящее время вставленные данные:

1   One         01  1
2   Two         02  1
3   Three       03  1
3   Threeeee    03  2
4   Four        04  2
5   Five        05  2
4   Four        04  3
5   Five        050 3
6   Six         06  3

Цель: вставить запись в переменную таблицы (или таблицу cte / temp), основываясь на уникальности, ТОЛЬКО ВКЛ [Id ] поле. «UNION» не сделал бы этого, потому что, как минимум, [Group] собирается сделать дубликатов записей, основываясь только на [Id] ... уникальных. Да, и значение [Group] в основном указывает на уровень важности, 1 = эти записи должны быть вставлены первыми, а 3 = эти записи должны быть вставлены последними, убедившись, что в целевой таблице нет других записей с таким же значением [Id] .

Ожидается, что данные будут вставлены:

1   One         01  1
2   Two         02  1
3   Three       03  1
4   Four        04  2
5   Five        05  2
6   Six         06  3

Я могу сделать это, сначала вставив [Group] = 1 записи в @ T1. Затем напишите еще одну вставку для [Group] = 2, где [Id] не существует, и так далее. Но я ищу эффективный способ. Я хочу сделать вставку эффективной.

1 Ответ

1 голос
/ 28 февраля 2020

Сначала создайте CTE со всеми строками, которые вы хотите вставить:

WITH cte(Id, Val1, Val2, [Group]) AS (
  SELECT 1, 'One', '01', 1
  UNION ALL
  SELECT 2, 'Two', '02', 1
  UNION ALL
  SELECT 3, 'Three', '03', 1
  UNION ALL
  SELECT 3, 'Threeeee', '03', 2
  UNION ALL
  SELECT 4, 'Four', '04', 2
  UNION ALL
  SELECT 5, 'Five', '05', 2
  UNION ALL
  SELECT 4, 'Four', '04', 3
  UNION ALL
  SELECT 5, 'Five', '050', 3
  UNION ALL
  SELECT 6, 'Six', '06', 3
)

, а затем в операторе INSERT вы можете использовать NOT EXISTS:

INSERT INTO @T1
SELECT c.* FROM cte c
WHERE NOT EXISTS (
  SELECT 1 FROM cte
  WHERE Id = c.ID AND [Group] < c.[Group]
);

См. Демоверсию . Или ROW_NUMBER() оконная функция:

INSERT INTO @T1
SELECT t.Id, t.Val1, t.Val2, t.[Group] 
FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY [GROUP]) rn
  FROM cte
) t
WHERE t.rn = 1;

См. Демонстрационную версию . Результаты:

> Id | Val1  | Val2 | Group
> -: | :---- | :--- | ----:
>  1 | One   | 01   |     1
>  2 | Two   | 02   |     1
>  3 | Three | 03   |     1
>  4 | Four  | 04   |     2
>  5 | Five  | 05   |     2
>  6 | Six   | 06   |     3
...