SQL для поиска уникальных идентификаторов - PullRequest
0 голосов
/ 20 октября 2019

Я хочу найти количество активных уникальных идентификаторов в конкретном диапазоне дат

CREATE TABLE tbl_tmp
(
    id integer,
    start_dt date,
    end_dt date,
    status varchar(8)
);

INSERT INTO tbl_tmp VALUES (30, '2015-11-22','2015-11-22', 'Active');
INSERT INTO tbl_tmp VALUES (30, '2015-11-23', '2015-12-06', 'Active');
INSERT INTO tbl_tmp VALUES (40, '2015-11-26', '2015-11-26', 'Active');
INSERT INTO tbl_tmp VALUES (40, '2015-11-27', '2016-02-23', 'Active');
INSERT INTO tbl_tmp VALUES (30, '2015-12-06', '2015-12-07', 'Inactive');
INSERT INTO tbl_tmp VALUES (40, '2016-02-24', '2016-08-04', 'Active');

Ожидаемый результат:

если предложение where в дату начала> = '2015-11-22 'и end_date <=' 2015-12-05 'количество уникальных идентификаторов должно быть 2, так как 30 и 40 активны в этом диапазоне времени </p>

, если предложение указано в дате начала> =' 2015-11-22 'и end_date <=' 2015-12-10 'количество уникальных идентификаторов должно быть 1, потому что 30 неактивно, начиная с' 2018-12-07 '</p>

Ответы [ 2 ]

0 голосов
/ 21 октября 2019

Я думаю, что вы более склонны к конечной дате, поскольку 30 активен с 22 до 06, но все же вы хотите, чтобы его статус был неактивным, так как он неактивен (в случае 2) с 06 по 07. Так что последний статус идентификатора - это то, чтоВы очень заинтересованы в.

Вы можете попробовать следующий запрос:

Select t.* -- or count(1) for fetching just count
(Select t.* , 
       row_number() 
        over (partition by id order by start_dt desc) as rn
from  your_table t
Where <date_conditions>) t
Where t.status = 'Active' and t.rn = 1;

Cheers !!

0 голосов
/ 21 октября 2019

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

select (count(distinct (case when 
                             then t.id
                        end)
                       )
              ) -
        count(distinct (case when t.end_dt >= r.range_start and
                                  t.start_dt <= r.range_end and
                                   t.status = 'Inactive'
                             then t.id
                        end)
              )
      ) as num_active_for_entire_range        
from tbl_temp t cross join
     (select date '2015-11-22' as range_start, date '2015-12-05' as range_end from dual
     ) r;

H

На самом деле, этопроще, если фильтрация выполняется один раз:

select (count(distinct t.id) -
        count(distinct (case when t.status = 'Inactive'
                             then t.id
                        end)
                       )
              )
      ) as num_active_for_entire_range        
from tbl_temp t cross join
     (select date '2015-11-22' as range_start, date '2015-12-05' as range_end
     ) r
where t.end_dt >= r.range_start and
      t.start_dt <= r.range_end

Здесь - это дБ <> скрипка.

...