Логика для отображения одного диапазона дат в другой диапазон дат? - PullRequest
0 голосов
/ 13 апреля 2019

У меня есть одна таблица истории пользователей с начальной и конечной датой. У меня есть вторая таблица истории ролей с датой начала и окончания.

Я пытаюсь взять таблицу истории пользователей и разбить ее на историю ролей. По сути, я пытаюсь отобразить историю ролей в историю пользователей.

Например:

Вот пользовательская таблица

| person | title       | roleid | start     | end         |
|--------|-------------|--------|-----------|-------------|
| a      | VP          | 1      | 10/1/2017 | 10/31/2017  |
| a      | Director    | NULL   | 11/1/2017 | 11/25/2017  |
| a      | NULL        | 2      | 11/26/2017| 12/5/2017   |
| a      | President   | 3      | 12/6/2017 | 12/31/2017  |
| a      | Exec        | 3      | 01/01/2018| 12/31/2999  |

и таблица истории ролей


| roleid | role        | xxxxxx | start      | end         |
|--------|-------------|--------|------------|-------------|
| 1      | Champion    | x      | 10/05/2017 | 11/01/2017  |
| 2      | Nerd        | x      | 10/20/2017 | 12/31/2999  |
| 3      | Peon        | x      | 11/26/2017 | 12/15/2017  |
| 3      | King        | x      | 12/16/207  | 12/31/2017  |

Я пытаюсь получить такой результат:

| person | title       | role_id | role   | start      | end         |
|--------|-------------|---------|--------|------------|-------------|
| a      | VP          | NULL    |NULL    | 10/01/2017 | 10/04/2017  |
| a      | VP          | 1       |champion| 10/05/2017 | 10/31/2017  |
| a      | Director    | NULL    |NULL    | 11/01/2017 | 11/25/2017  |
| a      | NULL        | 2       |nerd    | 11/26/2017 | 12/05/2017  |
| a      | President   | 3       |peon    | 12/06/2017 | 12/15/2017  |
| a      | President   | 3       |King    | 12/16/2017 | 12/31/2017  |
| a      | Exec        | 3       |King    | 01/01/2018 | 12/31/2999  |

Я пытался подойти к этому с помощью нескольких операторов вставки, но я продолжаю неправильно понимать логику. Любая помощь будет оценена.

Ответы [ 2 ]

0 голосов
/ 13 апреля 2019

Я нашел ответ, который мне помог.

«То, что у вас есть, это два медленно меняющихся типа 2 (SCD). Обычно, когда вы запрашиваете данные этого типа, вы используете один момент времени для разрезания данных. Но перекрывая их?

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

Во-первых, тестирует перекрывающиеся диапазоны . Серьезно, добавьте этот ответ в закладки. Это удивительно, и я возвращаюсь к этому в течение многих лет!

Вы собираетесь применить упрощенное выражение из этого ответа к объединению двух таблиц: A.Start <= B.End AND A.End> B.Start

Это закончится с декартовым результатом - это нормально. Действительный эффективный диапазон каждой строки - это наименьшее перекрывающееся окно из двух таблиц:

, ПРИМЕР, КОГДА A.Start> B.Start THEN A.Start ELSE B.Start END AS New_Start , ДЕЛА, КОГДА A.End И это должно дать вам новый денормализованный набор результатов SCD типа 2.

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

Надеюсь, это то, что вы искали! ”

0 голосов
/ 13 апреля 2019

Во-первых: Я создаю виртуальный первичный ключ в «пользовательской таблице» с помощью функции row_number, как показано ниже.

select *,ROW_NUMBER() OVER(order by person ,start) as vkey from 'user table'

Используя приведенную выше таблицу, я притворяюсь, что она «временная», чтобы узнать, к какой строке vkey мы должны присоединиться к «таблице истории ролей»:

    select vkey,rn 
from(select * ,ROW_NUMBER() OVER (PARTITION BY person,roleid 
order by start) as rn) from 'temptable')temp where rn<=1

После получения vkey мы можем присоединиться к «таблице истории ролей», чтобы получить желаемый результат (я претендую на приведенную выше таблицу как «keytable»):

    select t1.person,t1.title,t1.role_id,t2.role,t1.start,t1.end from 'temptable' t1 
left join 'role history table' t2 on t1.role_id=t2.role_id 
and t1.vkey in (select vkey from 'keytable') order by t1.vkey
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...