我需要计算每个日期的不同ID的数量。有没有办法只使用SQL,而不使用PL / SQL?
create table test (
id number(10),
start_date timestamp,
end_date timestamp
);
insert into test values(1, to_date('01.01.2019', 'dd.mm.yyyy'), to_date('03.01.2019', 'dd.mm.yyyy'));
insert into test values(2, to_date('02.01.2019', 'dd.mm.yyyy'), to_date('05.01.2019', 'dd.mm.yyyy'));
insert into test values(3, to_date('04.01.2019', 'dd.mm.yyyy'), to_date('06.01.2019', 'dd.mm.yyyy'));
我需要一个SELECT
语句来得到这样的东西:
01.01.2019 1
02.01.2019 2
03.01.2019 2
04.01.2019 2
05.01.2019 2
06.01.2019 1
解决此问题的关键是生成一个日期列表,您希望计算不同ID的数量。你可以简单地用表格JOIN
这个列表并打开聚合。
这是一个简单的解决方案,它根据原始表中包含日期的两列中可用的不同值构建日期列表。使用递归子查询或日历表存在其他(更好)选项。
SELECT dt.mydate, COUNT(DISTINCT id_number) cnt
FROM
(
SELECT DISTINCT start_date mydate FROM test
UNION ALL SELECT DISTINCT end_date FROM test
) dt
LEFT JOIN test t ON dt.mydate >= t.start_date AND dt.mydate <= t.end_date
GROUP BY dt.mydate
ORDER BY dt.mydate
这个带有样本数据的demo on DB Fiddle返回:
MYDATE | CNT :--------------------------- | --: 01-JAN-19 12.00.00.000000 AM | 1 02-JAN-19 12.00.00.000000 AM | 2 03-JAN-19 12.00.00.000000 AM | 2 04-JAN-19 12.00.00.000000 AM | 2 05-JAN-19 12.00.00.000000 AM | 2 06-JAN-19 12.00.00.000000 AM | 1
另一种可以尝试使用cte递归的方法
WITH CTE(id,start_date,end_date) AS
(
SELECT id,start_date ,end_date
FROM test
UNION ALL
SELECT id,start_date ,cast((end_date - 1) as date)
FROM CTE
WHERE start_date <= cast((end_date - 1) as date)
)
SELECT end_date,COUNT(*)
FROM CTE
GROUP BY end_date
ORDER BY end_date
或者使用CONNECT BY
SELECT dt,count(*)
FROM (
SELECT DISTINCT end_date,start_date + LEVEL dt
FROM test
CONNECT BY extract(day from end_date - start_date) - LEVEL + 1 >= 0
) t1
GROUP BY dt
ORDER BY dt
SELECT start_date,COUNT(Id_number) from test group by start_date
这种方式允许您按日期(开始日期或结束日期,您喜欢的任何方式)对行进行分组,并计算具有相同日期的行。
我希望它对你有所帮助。