分类重叠类型 - Oracle
Posted
技术标签:
【中文标题】分类重叠类型 - Oracle【英文标题】:Categorize Overlap Type - Oracle 【发布时间】:2019-07-15 15:27:07 【问题描述】:我已经能够使用 How do I find the total number of used days in a month? 来回答我们养猫和狗的 TOTAL 天数,这很有帮助,但我需要知道我们养了多少天:
Cats only: 4
Dogs only: 5
Both: 6
提前谢谢你!
CREATE TABLE "ANIMALGUESTS"
( "ID" NUMBER,
"GUESTNAME" VARCHAR2(20 BYTE),
"GUESTTYPE" VARCHAR2(20 BYTE),
"CHECKIN" DATE,
"CHECKOUT" DATE
);
Insert into ANIMALGUESTS (ID,GUESTNAME,GUESTTYPE,CHECKIN,CHECKOUT) values (1,'Tom','Cat',to_date('01-JAN-19','DD-MON-RR'),to_date('10-JAN-19','DD-MON-RR'));
Insert into ANIMALGUESTS (ID,GUESTNAME,GUESTTYPE,CHECKIN,CHECKOUT) values (2,'Spike','Dog',to_date('03-JAN-19','DD-MON-RR'),to_date('05-JAN-19','DD-MON-RR'));
Insert into ANIMALGUESTS (ID,GUESTNAME,GUESTTYPE,CHECKIN,CHECKOUT) values (3,'Spike','Dog',to_date('08-JAN-19','DD-MON-RR'),to_date('12-JAN-19','DD-MON-RR'));
Insert into ANIMALGUESTS (ID,GUESTNAME,GUESTTYPE,CHECKIN,CHECKOUT) values (4,'Cherie','Cat',to_date('07-JAN-19','DD-MON-RR'),to_date('09-JAN-19','DD-MON-RR'));
Insert into ANIMALGUESTS (ID,GUESTNAME,GUESTTYPE,CHECKIN,CHECKOUT) values (5,'Tyke','Dog',to_date('10-JAN-19','DD-MON-RR'),to_date('15-JAN-19','DD-MON-RR'));
【问题讨论】:
第一个输出是你已经拥有的,还是你想通过一些查询生成的? @TimBiegeleisen 抱歉,我不清楚,这就是我需要的结果。我已经能够使用链接的解决方案来回答cats: 10 and dogs: 11
,而不管差距和重叠。
【参考方案1】:
使用条件聚合和内联日历表:
WITH cte AS (
SELECT DATE '2019-01-01' + rownum -1 dt FROM DUAL CONNECT BY ROWNUM < 366
)
SELECT DISTINCT
SUM(CASE WHEN COUNT(DISTINCT GUESTTYPE)=2 THEN 1 END) OVER() AS both,
SUM(CASE WHEN COUNT(DISTINCT GUESTTYPE)=1 AND MIN(GUESTTYPE)='Cat' THEN 1 END) OVER() AS cats_only,
SUM(CASE WHEN COUNT(DISTINCT GUESTTYPE)=1 AND MIN(GUESTTYPE)='Dog' THEN 1 END) OVER() AS dogs_only
FROM cte c
LEFT JOIN "ANIMALGUESTS" a ON c.dt BETWEEN a.CHECKIN AND a.CHECKOUT
GROUP BY dt;
db<>fiddle demo
【讨论】:
谢谢!这看起来会奏效。我必须在未来证明connect by
,但我认为这会很好。【参考方案2】:
Oracle 12c 支持递归 CTE,因此您可以扩展数据然后聚合:
with cte as (
select checkin as dt, checkout, guesttype
from ANIMALGUESTS
union all
select dt + 1, checkout, guesttype
from cte
where dt < checkout
)
select sum(case when cats > 0 and dogs > 0 then 1 else 0 end) as both,
sum(case when cats > 0 and dogs = 0 then 1 else 0 end) as cats_only,
sum(case when cats = 0 and dogs > 0 then 1 else 0 end) as dogs_only
from (select dt, sum(case when guesttype = 'Cat' then 1 else 0 end) as cats,
sum(case when guesttype = 'Dog' then 1 else 0 end) as dogs
from cte
group by dt
) cte;
这会将结果集生成为一行中的列,而不是单独的行。
【讨论】:
以上是关于分类重叠类型 - Oracle的主要内容,如果未能解决你的问题,请参考以下文章