Поиск случайной выборки уникальных данных в нескольких столбцах - SQL Сервер - PullRequest
2 голосов
/ 15 января 2020

При наличии набора данных в SQL базе данных сервера со следующими столбцами

AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2

Все три столбца являются первичными ключами из одной и той же таблицы пользователей. Мне нужно найти случайную выборку, которая будет включать в себя все UserID, доступные во всех трех столбцах, независимо от положения, гарантируя при этом наименьшее число уникальных AccountID.

--SET UP TEST DATA
CREATE TABLE MY_TABLE 
(
    AccountID int, 
    UserID_Salesperson int, 
    UserID_Servicer1 int, 
    UserID_Servicer2 int
)

INSERT INTO MY_TABLE (AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2) 
VALUES (12345, 1, 1, 2)
INSERT INTO MY_TABLE (AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2) 
VALUES (12346, 3, 2, 1)
INSERT INTO MY_TABLE (AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2) 
VALUES (12347, 4, 3, 1)
INSERT INTO MY_TABLE (AccountID, UserID_Salesperson, UserID_Servicer1, UserID_Servicer2) 
VALUES (12348, 1, 2, 3)

--VIEW THE NEW TABLE
SELECT * FROM MY_TABLE

--NORMALIZE DATA (Unique List of UserID's) 
SELECT DISTINCT MyDistinctUserIDList 
FROM
    (SELECT UserID_Salesperson as MyDistinctUserIDList, 'Sales' as Position 
     FROM MY_TABLE
     UNION 
     SELECT UserID_Servicer1, 'Service1' as Position 
     FROM MY_TABLE
     UNION 
     SELECT UserID_Servicer2, 'Service2' as Position 
     FROM MY_TABLE) MyDerivedTable

--NORMALIZED DATA
SELECT * 
FROM
    (SELECT AccountID, UserID_Salesperson as MyDistinctUserIDList, 'Sales' as Position 
     FROM MY_TABLE
     UNION 
     SELECT AccountID, UserID_Servicer1, 'Service1' as Position 
     FROM MY_TABLE
     UNION 
     SELECT AccountID, UserID_Servicer2, 'Service2' as Position 
     FROM MY_TABLE) MyDerivedTable

DROP TABLE MY_TABLE

Для таблицы этого примера я Можно выбрать AccountID (12347 и 12348) ИЛИ (12347 и 12346), чтобы получить наименьшее количество учетных записей со всеми пользователями.

Мое текущее решение неэффективно и может допускать ошибки. В настоящее время я выбираю случайное значение AccountID, вставляю данные в временную таблицу и пытаюсь найти следующую вставку из того, что я еще не поместил в временную таблицу. Я просматриваю записи до тех пор, пока не найду что-то, что раньше не использовалось ... и через несколько тысяч циклов он сдастся и выберет любую запись.

1 Ответ

0 голосов
/ 15 января 2020

Я не знаю, как вы гарантируете наименьшее количество идентификаторов учетных записей, но вы можете получить одну строку для идентификатора пользователя, используя:

select t.*
from (select t.*,
             row_number() over (partition by UserId order by newid()) as seqnum
      from my_table t cross apply
           (values (t.UserID_Salesperson), (t.UserID_Servicer1), (t.UserID_Servicer2)
           ) v(UserID)
     ) t
where seqnum = 1;

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

select top (1) with ties t.*
from (select t.*,
             row_number() over (partition by UserId order by newid()) as seqnum
      from my_table t cross apply
           (values (t.UserID_Salesperson), (t.UserID_Servicer1), (t.UserID_Servicer2)
           ) v(UserID)
     ) t
where seqnum = 1
order by row_number() over (partition by accountID order by accountID);
...