Фильтровать дубликаты записей - PullRequest
1 голос
/ 22 октября 2019

Я пытаюсь определить отдельный список person_id, который имеет тот же account_id, что и другой человек.

Предостережение - это person_id, которому в последний раз дали перекрытие account_id, не следует включать в этот список.

        id          person_id     account_id
   +------------------------------------------+
   |            |             |               |
   |     1      |     1       |      10       |
   +------------------------------------------+
   |            |             |               |
   |     2      |     2       |      10       |
   +------------------------------------------+
   |            |             |               |
   |     3      |     3       |      11       |
   +------------------------------------------+

обратите внимание : это несколько упрощенный пример, который не следует воспринимать буквально.


Это запрос, который у меня есть в настоящее время

SELECT STRING_AGG(person_id, ',')
FROM accounts_map
WHERE created_at > '2001-01-10' -- ignore records smaller than 2001-01-10
GROUP BY account_id -- group by account id
HAVING count(*) > 1 -- any account that have multiple matches

Что я не могу понять, так это

  1. Как при каждом совпадении account_id совпадать, исключая последнюю запись
  2. Как игнорировать записи, в которых account_id помечен как нулевой, почему-то <> NULL не работает
CREATE TABLE accounts_map
    ([id] int, [person_id] int, [account_id] int, [created_at] DATETIME)
;

INSERT INTO accounts_map
    ([id], [person_id], [account_id], [created_at])
VALUES
    (1, 1, 10, '2001-01-10'),
    (2, 1, 11, '2001-01-10'),
    (2, 1, 12, '2001-01-10'),

    (3, 2, 20, '2019-01-11'),
    (4, 2, 21, '2019-01-11'),
    (5, 2, 22, '2019-01-11'),

    (3, 3, 30, '2019-01-12'),
    (4, 3, 31, '2019-01-12'),
    (5, 3, 32, '2019-01-12'),

    -- same account ids as records with id (1,2,3) but inserted in different order
    (6, 4, 12, '2019-01-13'),
    (7, 4, 11, '2019-01-13'),
    (8, 4, 10, '2019-01-13'),

    -- same account ids as records with id (3,4,5)
    (9, 5, 20, '2019-01-14'),
    (10, 5, 21, '2019-01-14'),
    (11, 5, 22, '2019-01-14'),

    -- same account ids as records with id (9,10,11)
    (12, 6, 20, '2019-01-15'),
    (13, 6, 21, '2019-01-15'),
    (14, 6, 22, '2019-01-15')
;

ожидаемый вывод

id
---
1 (not expected if date range cutoff specified) created_at > '2001-01-10'
2
4 (not expected if date range cutoff specified) created_at > '2001-01-10'
5

Еслиу него есть перекрывающаяся учетная запись, последний пользователь, которому была предоставлена ​​учетная запись, становится действительным и портит старые.

http://sqlfiddle.com/#!18/f53e5/1

1 Ответ

2 голосов
/ 22 октября 2019

В подзапросе вы можете подсчитать количество окон в группах записей с одинаковым account_id и использовать row_number() для ранжирования их по дате. Затем внешний запрос фильтрует записи, количество окон которых больше 1, и возвращает все записи, кроме самой последней:

select person_id, account_id, created_at
from (
    select 
        t.*, 
        row_number() over(partition by account_id order by created_at desc) rn,
        count(*) over(partition by account_id) cnt
    from accounts_map t
) t
where cnt > 1 and rn > 1

Демонстрация на БД Fiddle :

person_id | account_id | created_at         
--------: | ---------: | :------------------
        1 |         10 | 10/01/2001 00:00:00
        1 |         11 | 10/01/2001 00:00:00
        1 |         12 | 10/01/2001 00:00:00
        5 |         20 | 14/01/2019 00:00:00
        2 |         20 | 11/01/2019 00:00:00
        5 |         21 | 14/01/2019 00:00:00
        2 |         21 | 11/01/2019 00:00:00
        5 |         22 | 14/01/2019 00:00:00
        2 |         22 | 11/01/2019 00:00:00

Примечание. Вы предоставили пример данных, но, к сожалению, не связали ожидаемые результаты, чтобы мы могли проверить вывод запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...