这是一个表格:
CREATE TABLE table_b (
name VARCHAR(255),
date_2 DATE,
date_3 DATE,
var CHAR(1)
);
INSERT INTO table_b (name, date_2, date_3, var) VALUES
('john', '2001-01-01', '2015-01-01', 'b'),
('sara', '2000-01-01', '2015-01-01', 'c'),
('sara', '2015-01-02', '2022-01-01', 'a'),
('tim', '2020-01-01', '2021-01-01', 'a'),
('john', '1998-01-01', '1999-01-01', 'd');
#table_b
name date_2 date_3 var
john 2001-01-01 2015-01-01 b
sara 2000-01-01 2015-01-01 c
sara 2015-01-02 2022-01-01 a
tim 2020-01-01 2021-01-01 a
john 1998-01-01 1999-01-01 d
在总体最小年份和最大年份之间,我想知道:每年,有多少人有此表中的记录?
这是我想到的方法:
with years as (
select 1998 as year
union all
select 1999
union all
##etc etc)
counts as
(select y.year
count(distinct t.name) as count
from table_b t
join years y
on t.date_2 <= date(y.year || '-12-31') and t.date_3 >= date(y.year || '-01-01')
group by y.year)
select * from counts;
有没有一种更简单的方法可以做到这一点,而无需手动列出所有年份?
您可以使用递归 CTE 从现有日期字段构建年份列表。您可以在 CTE 内获取最小日期(来自
date_2
)和 UNION ALL
,并具有最大年份的停止条件(来自 date_3
)。
此示例假设
date_2
始终小于相应的 date_3
。
WITH YEARS_LIST (YR, YR_STOP) AS (
SELECT
YEAR(MIN(DATE_2)) AS YR,
YEAR(MAX(DATE_3)) AS YR_STOP
FROM TABLE_B
UNION ALL
-- Generate a row for each year until we get to the max year
SELECT
YR + 1 AS YR,
YR_STOP
FROM YEARS_LIST
WHERE YR < YR_STOP
),
COUNTS AS (
SELECT
Y.YR,
COUNT(DISTINCT T.NAME) AS REC_COUNT
FROM TABLE_B AS T
INNER JOIN YEARS_LIST AS Y
ON
T.DATE_2 <= DATE(Y.YR || '-12-31')
AND T.DATE_3 >= DATE(Y.YR || '-01-01')
GROUP BY Y.YR
)
SELECT *
FROM COUNTS;
注意:我修改了示例中的一些列名称,以避免使用某些关键字(例如 YEAR、COUNT)。
CTE 的第一次迭代将生成如下行:
年 | YR_STOP |
---|---|
1998 | 2022 |
CTE 中的第二个 select 语句将循环,生成一行,其中
YR
加 1,直到 YR
等于或大于 YR_STOP
。
生成的 CTE 将类似于以下内容:
年 | YR_STOP |
---|---|
1998 | 2022 |
1999 | 2022 |
2000 | 2022 |
... | ... |
2021 | 2022 |
2022 | 2022 |