Добавление нового столбца с набором правил в SQL Server - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть несколько сложный набор правил, которые мне нужно выполнить для таблицы. Проблема заключается в следующем: у меня есть таблица, в которой хранятся медицинские записи, и мне нужно определить первый сайт, на который человек заходит после даты выписки. Датой выписки является end_date с местоположением 'initial' (это будет первая строка для каждой группы). Таблица сгруппирована по идентификатору и отсортирована в формате, показанном ниже.

Существует 3 правила: (1) в группе идентификаторов, если какая-либо из строк имеет начало_даты, совпадающее с первыми строками end_date, вернуть это местоположение как первый сайт (если есть две строки, удовлетворяющие этому условию, либо верны, первый экземпляр предпочтителен). (2) если первая опция не существует, то если есть экземпляр, в котором у пациента было местоположение «Здоровье», верните «Здоровье». (3) в противном случае, если условия 1 и 2 не существуют, вернуть «Домой»

таблица

ID    color  begin_date    end_date     location
1     red    2017-01-01    2017-01-07   initial
1     green  2017-01-05    2017-01-07   nursing
1     blue   2017-01-07    2017-01-15   rehab
1     red    2017-01-11    2017-01-22   Health
2     red    2017-02-22    2017-02-26   initial
2     green  2017-02-26    2017-02-28   nursing
2     blue   2017-02-26    2017-02-28   rehab
3     red    2017-03-11    2017-03-22   initial
4     red    2017-04-01    2017-04-07   initial
4     green  2017-04-05    2017-04-07   nursing
4     blue   2017-04-10    2017-04-15   Health

окончательный результат:

ID    first_site
1     rehab
2     nursing
3     home
4     Health

В sql-server 2008 моя попытка: (примечание: я рассмотрел добавление вспомогательного столбца, который будет конечной датой 'начального' местоположения для каждой строки, чтобы было проще сравнивать внутри строки. Не уверен, если это необходимо ). Я ценю любое руководство!

SELECT
ID,
OVER( PARTITION ID CASE WHEN end_date[0] = begin_date THEN location
                        WHEN location = 'Health' THEN 'Health'
                        ELSE 'Home' end) AS [first_site]
FROM table

В python мне удалось получить этот ответ:

def conditions(x):
    #compare each group first
    val = x.loc[x['begin_date'] == x['end_date'].iloc[0], 'location']
    #if at least one match (not return empty `Series` get first value)
    if not val.empty:
        return val.iloc[0]
    #if value is empty, check if value 'Health' exists within the group 
    elif (x['location']  == 'Health').any():
        return 'Health'
    else:
        return 'Home'

final = df.groupby('ID').apply(conditions).reset_index(name='first_site')

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Этого можно достичь с помощью оконной функции для ранжирования посещений, которые начинаются в тот же день, что и конец initial, а затем пару простых join s:

declare @t table(ID int,color varchar(20),begin_date date,end_date date,location varchar(20));
insert into @t values(1,'red','20170101','20170107','initial'),(1,'green','20170105','20170107','nursing'),(1,'blue','20170107','20170115','rehab'),(1,'red','20170111','20170122','Health'),(2,'red','20170222','20170226','initial'),(2,'green','20170226','20170228','nursing'),(2,'blue','20170226','20170228','rehab'),(3,'red','20170311','20170322','initial'),(4,'red','20170401','20170407','initial'),(4,'green','20170405','20170407','nursing'),(4,'blue','20170410','20170415','Health');

with d as
(
    select ID
        ,color
        ,begin_date
        ,end_date
        ,location
        ,row_number() over (partition by ID
                                        ,begin_date
                            order by case when location = 'initial' then '29990101' else begin_date end
                            ) as r
    from @t
)
select i.ID
        ,isnull(d.location,isnull(h.location,'Home')) as first_site
from d as i
    left join d
        on i.end_date = d.begin_date
            and d.r = 1
    left join d as h
        on i.ID = h.ID
            and h.location = 'Health'
where i.location = 'initial'
;

Выход:

+----+------------+
| ID | first_site |
+----+------------+
|  1 | rehab      |
|  2 | nursing    |
|  3 | Home       |
|  4 | Health     |
+----+------------+
0 голосов
/ 26 апреля 2018
declare @example table (
    ExampleID   int identity(1,1) not null primary key clustered
,   ID          int not null
,   Color       nvarchar(255) not null
,   BeginDate   date not null
,   EndDate     date not null
,   Loc         nvarchar(255) not null
);

insert into @example (ID, color, begindate, enddate, loc)

select 1, 'red'   , '2017-01-01', '2017-01-07', 'initial' union all
select 1, 'green'  , '2017-01-05', '2017-01-07', 'nursing' union all
select 1, 'blue'  , '2017-01-07', '2017-01-15', 'rehab' union all
select 1, 'red'  , '2017-01-11', '2017-01-22', 'Health' union all
select 2, 'red'  , '2017-02-22', '2017-02-26', 'initial' union all
select 2, 'green'  , '2017-02-26', '2017-02-28', 'nursing' union all
select 2, 'blue'  , '2017-02-26', '2017-02-28', 'rehab' union all
select 3, 'red'  , '2017-03-11', '2017-03-22', 'initial' union all
select 4, 'red'  , '2017-04-01', '2017-04-07', 'initial' union all
select 4, 'green'  , '2017-04-05', '2017-04-07', 'nursing' union all
select 4, 'blue'  , '2017-04-10', '2017-04-15', 'Health';

    with cte as (
        select a.ID
             , a.Color
             , a.BeginDate
             , a.EndDate
             , b.Loc 
             , rank() over(partition by a.ID order by a.ID, a.begindate, b.enddate desc, b.loc) Ranking
          from @example a
     left join @example b
            on a.EndDate = b.BeginDate
                )
    , cte2 as (
        select id
             , Loc
          from @example
         where loc = 'health'
                )

    select a.ID
         , COALESCE(a.loc, b.loc, 'Home') as Loc 
      from cte a
 left join cte2 b
        on a.id = b.id
      where Ranking = 1

Выход:

ID  Loc
1   rehab
2   nursing
3   home
4   Health
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...