Sql ORACLE:通过一个选择查看不同的日期范围
我希望能够计算出一年中不同日期的不同年龄段,而不必全部合并 现在的查询如下所示:Sql ORACLE:通过一个选择查看不同的日期范围,sql,oracle,Sql,Oracle,我希望能够计算出一年中不同日期的不同年龄段,而不必全部合并 现在的查询如下所示: SELECT to_char(last_day(add_months(sysdate,-1)),'YYYYMM') yrmnth, FLOOR(months_between(last_day(add_months(sysdate,-1)),birth_date)/12), count(distinct id) members from agefile WHERE
SELECT
to_char(last_day(add_months(sysdate,-1)),'YYYYMM') yrmnth,
FLOOR(months_between(last_day(add_months(sysdate,-1)),birth_date)/12),
count(distinct id) members
from agefile
WHERE to_char(from_date, 'YYYYMM')<=to_char(last_day(add_months(sysdate,-1)),'YYYYMM')
and to_char(thru_date, 'YYYYMM')>=to_char(last_day(add_months(sysdate,-1)),'YYYYMM')
GROUP BY to_char(last_day(add_months(sysdate,-1)),'YYYYMM'),
FLOOR(months_between(last_day(add_months(sysdate,-1)),birth_date)/12)
UNION ALL
SELECT
to_char(last_day(add_months(sysdate,-2)),'YYYYMM') yrmnth,
FLOOR(months_between(last_day(add_months(sysdate,-2)),birth_date)/12),
count(distinct id) members
from agefile
WHERE to_char(from_date, 'YYYYMM')<=to_char(last_day(add_months(sysdate,-2)),'YYYYMM')
and to_char(thru_date, 'YYYYMM')>=to_char(last_day(add_months(sysdate,-2)),'YYYYMM')
GROUP BY to_char(last_day(add_months(sysdate,-2)),'YYYYMM'),
FLOOR(months_between(last_day(add_months(sysdate,-2)),birth_date)/12)
UNION ALL
and so on...
因此,我不希望将agefile传递12次,而是希望传递一次,但输出12倍的ages
例如:
yrmnth age members
201809 1 100
201809 2 120
201809 3 145
201808 1 56
在过去的12个月中,截至每个月的最后一天,有多少会员是x岁,这将是一个商业问题
有没有办法绕过将文件传递12次并使用一个select来执行此操作
谢谢不要硬编码整数,而是要交叉连接到整数集 你可以这样做:
SELECT ROWNUM as rn FROM agefile
WHERE ROWNUM <= 12
在这种情况下,如果交叉应用于月份列表而不是整数列表,它的清理效果会更好,并且有一个预构建的数字/理货表可以让它更干净。在with子句中构建月份,并交叉连接表:
with months as
(
select last_day(add_months(sysdate, -1)) as day from dual
union all
select last_day(add_months(sysdate, -2)) as day from dual
union all
...
)
select
to_char(months.day,'yyyymm') yrmnth,
floor(months_between(months.day, birth_date) / 12),
count(distinct id) members
from months cross join agefile
where to_char(from_date, 'yyyymm') <= to_char(months.day, 'yyyymm')
and to_char(thru_date, 'yyyymm') >= to_char(months.day, 'yyyymm')
group by
to_char(months.day, 'yyyymm'),
floor(months_between(months.day, birth_date) / 12);
您的查询执行了大量冗余操作,可以进行大量清理:
WITH m AS(
SELECT last_day(add_months(sysdate,level-12)) month_end FROM dual CONNECT BY level <=12
)
SELECT
m.month_end,
trunc(months_between(af.birth_date, .month_end)) as age_at,
count(*) as num_mem
FROM
age_file af
CROSS JOIN
m
GROUP BY
m.month_end,
trunc(months_between(af.birth_date, .month_end))
我不太清楚起始日期和截止日期的意义是什么,除非它是活动成员的过滤器,在这种情况下,它可能表示为af.from_日期和af.thru_日期之间的m.month_结束位置
在你的查询中,所有大量的操作日期和炭化都是不必要的——如果你马上要通过只计算一个月的最后一天等方式来减少一天的时间,那么就不需要计算一个月的最后一天
我建议您将日期保留在日期中,因为这更清楚地表明,所表示的年龄是在一个月的最后一天-我认为很多人在查看一个月的日期时默认的假设是,它指的是一个月的开始
目前,此查询还计算当前月份。如果您只希望前12个月不包括当前月份,请在级别查询中选择-13。查询产生1到12,减去12意味着它是-12到0。减去13等于-13到-1请编辑您的帖子,突出显示您的SQL,然后按{}按钮,m为选择最后一天添加月日期,一级月底从dual CONNECT BY level良好捕获,修复了错误
WITH m AS(
SELECT last_day(add_months(sysdate,level-12)) month_end FROM dual CONNECT BY level <=12
)
SELECT
m.month_end,
trunc(months_between(af.birth_date, .month_end)) as age_at,
count(*) as num_mem
FROM
age_file af
CROSS JOIN
m
GROUP BY
m.month_end,
trunc(months_between(af.birth_date, .month_end))