我需要从第一个表中提取月份字段,我希望结果看起来像第二个表。
我知道使用EXTRACT(MONTH FROM BEGIN_DATE)获取月份,但我不确定如何显示所有日期字段。有任何想法吗?使用Oracle SQL。
答案 0 :(得分:1)
这是一种方法。请注意,我将列名从Month
更改为mth
(“month”是Oracle关键字,不应将其用作表名或列名)。我还会显示完整的月份描述(即包括年份),这样当同一个月(例如9月)对同一个person_id
不止一次时,就不会产生混淆。您可以通过调整TO_CHAR
中的格式模型来更改它以显示月份,但这对我来说没有多大意义。
测试数据位于WITH子句中,该子句不是SQL查询的一部分;删除它,并在SELECT查询中使用实际的表名(而不是我在WITH子句中创建的虚构名称)。
with
inputs ( person_id, begin_date, end_date ) as (
select 123, date '2017-11-01', date '2199-12-31' from dual union all
select 654, date '2017-09-01', date '2017-10-31' from dual union all
select 789, date '2017-12-01', date '2199-12-31' from dual
)
select person_id,
to_char(add_months(trunc(begin_date, 'mm'), level - 1), 'mm-yyyy') as mth,
case when add_months(trunc(begin_date, 'mm'), level - 1) <= end_date
then 'Y' else 'N' end as yn
from inputs
connect by add_months(trunc(begin_date, 'mm'), level - 1) <= sysdate
and prior person_id = person_id
and prior sys_guid() is not null
order by person_id, level
;
PERSON_ID MTH YN
---------- ------- --
123 11-2017 Y
123 12-2017 Y
123 01-2018 Y
654 09-2017 Y
654 10-2017 Y
654 11-2017 N
654 12-2017 N
654 01-2018 N
789 12-2017 Y
789 01-2018 Y
10 rows selected
还有一件事 - 在示例数据中,您的begin_date
始终是一个月的开头。如果这是有保证的,那么你可以简化代码 - 不需要trunc( ..., 'mm')
- 但我仍然不会改变它;你不知道该列的这个特殊属性是否会继续使用,如果它发生了变化,你会很高兴代码已经解决了它。
答案 1 :(得分:0)
我想我终于理解了你想要的东西;你是SYSDATE正在运行查询。基于此,您希望获得每个PERSON_ID在BEGIN_DATE和SYSDATE之间的所有月份。
如果是这样,请点击此处:
SQL> with test (person_id, begin_date) as
2 (select 123, date '2017-11-01' from dual union
3 select 654, date '2017-09-01' from dual
4 )
5 select person_id,
6 to_char(add_months(trunc(begin_date, 'mm'), column_value - 1), 'mm') mon
7 from test,
8 table(cast(multiset
9 (select level lvl from dual
10 connect by level <= round(months_Between (sysdate, begin_date)) + 1)
11 as sys.odcinumberlist))
12 order by 1, 2;
PERSON_ID MO
---------- --
123 01
123 11
123 12
654 01
654 09
654 10
654 11
654 12
8 rows selected.
SQL>
答案 2 :(得分:0)
Mathguy答案的变体:
SELECT
person_id
, TO_CHAR(ADD_MONTHS(begin_date, LEVEL-1), 'mm') m
, TO_CHAR(ADD_MONTHS(begin_date, LEVEL-1), 'yyyy') y
, CASE WHEN ADD_MONTHS(begin_date, LEVEL-1) BETWEEN begin_date and end_date THEN 'Y' ELSE 'N' END AS yn
FROM
person_table
CONNECT BY
LEVEL <= MONTHS_BETWEEN(TRUNC(SYSDATE, 'MON'), TRUNC(begin_date, 'MON')) + 1
AND prior person_id = person_id
AND prior sys_guid() IS NOT NULL
ORDER BY
person_id, y, m;
SQLFiddle供参考。