提取日期字段

时间:2018-01-05 15:42:06

标签: sql oracle date

我需要从第一个表中提取月份字段,我希望结果看起来像第二个表。

我知道使用EXTRACT(MONTH FROM BEGIN_DATE)获取月份,但我不确定如何显示所有日期字段。有任何想法吗?使用Oracle SQL。

enter image description here

enter image description here

3 个答案:

答案 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供参考。