Sql 分类重叠类型-Oracle

Sql 分类重叠类型-Oracle,sql,oracle,oracle12c,Sql,Oracle,Oracle12c,我可以用它来回答我们养猫养狗的总天数,这很有帮助,但我需要知道我们养猫养狗的总天数: 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 ANIMA

我可以用它来回答我们养猫养狗的总天数,这很有帮助,但我需要知道我们养猫养狗的总天数:

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'));

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;

这会将结果集生成为行中的列,而不是单独的行。

使用条件聚合和内联日历表:

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;

第一个输出是您已经拥有的,还是您希望通过某个查询生成的?@TimBiegeleisen抱歉,我不清楚,这就是我需要的结果。我已经能够使用链接的解决方案来回答猫:10和狗:11,而不考虑间隙和重叠。谢谢!这看起来会有用的。我必须证明未来的连接,但我认为这将工作得很好。