Как найти повторяющиеся значения для групп с помощью SQL?

#sql #postgresql

Вопрос:

Я пытаюсь найти повторения между строками на основе столбца. Я пробовал оконные функции с row_number() / rank (), но они группируют все найденные значения (аналогично GROUP BY), чего я не ожидаю. Как я могу найти повторения значений?

Я пытался сделать что-то вроде этого:

SELECT *, rank() OVER(PARTITION BY customer ORDER BY id) FROM customers ORDER BY id

И получил следующий результат:

ID покупатель ранг
1 пользователь_1 1
2 клиент_2 1
3 клиент_2 2
4 пользователь_1 2
5 customer_3 1
6 пользователь_1 3

Что я хочу сделать:

ID покупатель ранг
1 пользователь_1 1
2 клиент_2 1
3 клиент_2 2
4 пользователь_1 1
5 customer_3 1
6 пользователь_1 1

Ответ №1:

Вы ищете количество в соседних строках. Это своего рода проблема пробелов и островов. Вы можете определить соседние строки с разницей row_numbers() в, а затем перечислить их:

 SELECT c.*, 
       ROW_NUMBER() OVER (PARTITION BY customer, seqnum - seqnum_2 ORDER BY id) as ranking
FROM (SELECT c.*,
             ROW_NUMBER() OVER (ORDER BY id) as seqnum,
             ROW_NUMBER() OVER (PARTITION BY customer ORDER BY id) as seqnum_2
      FROM customers c
     ) c
ORDER BY id
 

Комментарии:

1. Спасибо, это работает. Неужели это действительно должен быть такой сложный запрос? Проблема казалась намного проще, чем она есть 🙂

2. @Jora . . . Это не особенно сложно.

Ответ №2:

Вы можете использовать рекурсивный запрос:

 WITH RECURSIVE repeatitions(id, customer, repeat_count) AS (
  SELECT id, customer, 1 as repeat_count
  FROM customers
  UNION ALL
  SELECT c.id, c.customer, r.repeat_count   1
  FROM customers c, repeatitions r
  WHERE c.id = r.id   1 AND c.customer = r.customer
)
SELECT id, customer, repeat_count
FROM repeatitions
ORDER by id
 

Я создал рабочую скрипку, чтобы продемонстрировать это.