Test table:
create table se246714 (
did char(1),
dt date
);
Test data:
insert into se246714 values
('A', '2019-01-01'),
('A', '2019-01-01'),
('A', '2019-01-02'),
('A', '2019-01-03'),
('B', '2019-01-01'),
('B', '2019-01-02'),
('B', '2019-01-03'),
('C', '2019-01-01'),
('C', '2019-01-02'),
('C', '2019-01-02'),
('C', '2019-01-03'),
('D', '2019-01-01'),
('D', '2019-01-02'),
('D', '2019-01-03');
Easy enough to get did that only occur once a day:
select did, dt, count(*)
from se246714
group by did,dt
having count(*)=1;
Result:
did dt count
A 2019-01-02 1
A 2019-01-03 1
B 2019-01-01 1
B 2019-01-02 1
B 2019-01-03 1
C 2019-01-01 1
C 2019-01-03 1
D 2019-01-01 1
D 2019-01-02 1
D 2019-01-03 1
This is where it gets a bit more convoluted. It all depends on how you want to pass the dates in...
I'll assume you want to get the date range from the full set of data in the table. If you don’t, you can modify the CTE to give the start & end dates.
I'll start with an expanded version of the answer to demonstrate how it works.
with rowsperday as (
select did, dt, count(*)
from se246714
group by did,dt
having count(*)=1
),
startdate as ( select min(dt) as startdate from se246714 ),
enddate as ( select max(dt) as enddate from se246714 ),
numdays as ( select enddate - startdate + 1 as numdays from startdate,enddate )
select did, count(*)
from rowsperday, numdays
group by did, numdays
having count(*) = numdays
;
We calculate the difference in dates to get the number of days involved, then check the count of dids to see if they appeared every day.
Slimmed down version:
with rowsperday as (
select did, dt, count(*)
from se246714
group by did,dt
having count(*)=1
)
select did, count(*)
from rowsperday
group by did
having count(*) = (select max(dt) - min(dt) + 1 from rowsperday)
;
If you're wondering what the with .... as ( stuff is, read about Common table Expressions here.
Fiddle link here.