У меня есть таблица с миллионом строк и 50+ столбцами, в которой я сохранил все изменения записей. Из-за очень большого размера таблицы необходимо удалить столбец и все впоследствии повторяющиеся записи.

ID   otherID   a     b   |    c  
----------------------------------------
1     10       1     2   |    1
2     10       1     2   |    2
3     20       2     2   |    3
4     10       1     2   |    4
5     10       10    2   |    5
6     10       10    2   |    6
7     10       1     2   |    7

Итак, допустим, я удаляю столбец C, и мне нужно сохранить только 1-ю уникальную запись. Мне нужны записи 1, 3, 5 и 7. Итак, мой вопрос: как мне сгруппировать по 1, 2 и 4, но не по строке 6?

2
Jove_v 27 Май 2016 в 13:43

3 ответа

Лучший ответ

Если я правильно понял, для данных:

DECLARE @T TABLE (
  ID INT, 
  otherID INT, 
  a INT, 
  b INT
);

INSERT 
INTO @T (
  ID,
  otherID, 
  a, 
  b
)
VALUES
  (1, 10, 1, 2),
  (2, 10, 1, 2),
  (3, 20, 2, 2),
  (4, 10, 1, 2),
  (5, 10, 10, 2),
  (6, 10, 10, 2),
  (7, 10, 1, 2)
;

Следующий запрос должен вернуть то, что вы ищете:

WITH grp AS (
  SELECT        ID,
                otherID,  
                a,  
                b,
                grp = ROW_NUMBER() OVER(PARTITION BY otherID ORDER BY (id))
               - ROW_NUMBER() OVER(PARTITION BY otherID, a, b ORDER BY (id))
   FROM        @T
), 
filter AS (
  SELECT       ID, 
               otherID,  
               a, 
               b,
               grp,
               rn = ROW_NUMBER() OVER(PARTITION BY grp, otherID, a, b ORDER BY (id))
  FROM         grp
)

DELETE
FROM           filter 
WHERE          rn >1;

SELECT         * 
FROM           @T 
ORDER BY       id

Это возвращает:

ID   otherID   a     b   
-------------------------
1    10        1     2
3    20        2     2
5    10        10    2
7    10        1     2

Вы можете увидеть это в действии на странице SQL Fiddle.

2
Jeremy Caney 6 Апр 2020 в 00:30

Вы можете использовать разницу в подходе row_number():

select min(Id), otherId, a, b
from (select t.*,
             (row_number() over (order by id) - 
              row_number() over (partition by otherId, a, b order by id)
             ) as grp
     ) t
group by otherId, a, b, grp;

Для строк с одинаковыми значениями в соседних строках различное количество строк является постоянным.

0
Gordon Linoff 27 Май 2016 в 10:52

U может получить 1, 3 и 5-ю строку, используя следующий запрос

 SELECT * FROM (SELECT tbl.*,
              ROW_NUMBER() OVER (PARTITION BY otherId, a, b ORDER BY id)
             AS rn
             FROM [tablename] tbl
     ) t
WHERE rn = 1

Но требование получения 7-й строки неясно, поскольку это не уникальная строка (такая же, как 1,2,4-я строка

0
Sharvari 27 Май 2016 в 11:23