如何在 Oracle SQL 中使用月份作为日期列

Posted

技术标签:

【中文标题】如何在 Oracle SQL 中使用月份作为日期列【英文标题】:How to use months as columns from date in Oracle SQL 【发布时间】:2020-11-14 21:23:47 【问题描述】:

我有一个包含类型、数字和日期的简单表格:

type | number | date
--------------------
  A  |      2 | 15-MAY-2015
  A  |      1 | 15-APR-2015
  B  |      9 | 03-DEC-2015

我需要根据类型添加数字。但我遇到的问题是生成的表需要将月份作为列:

type | April | May | December
-----------------------------
  A  |     1 |   2 |       0
  B  |     0 |   0 |       9

如何将月份名称用作列?

我设法使用此函数TO_CHAR(table.date, 'Month') AS month 获取月份的名称。

【问题讨论】:

【参考方案1】:

这是一种选择(第 1 - 5 行的示例数据):

SQL> with test (type, num, datum) as
  2    (select 'A', 2, date '2015-05-15' from dual union all
  3     select 'A', 1, date '2015-04-15' from dual union all
  4     select 'B', 9, date '2015-12-03' from dual
  5    )
  6  select type,
  7    max(case when to_char(datum, 'mm') = '04' then num else 0 end) as april,
  8    max(case when to_char(datum, 'mm') = '05' then num else 0 end) as may,
  9    max(case when to_char(datum, 'mm') = '12' then num else 0 end) as december
 10  from test
 11  group by type
 12  order by type;

T      APRIL        MAY   DECEMBER
- ---------- ---------- ----------
A          1          2          0
B          0          0          9

SQL>

【讨论】:

嗨,这几乎解决了我的问题。问题是我需要对这些值求和,但您的代码仅将数字替换为 num。抱歉,因为在我的示例中,您看不到正在添加的数字。 在这种情况下,使用 SUM 函数代替 MAX。【参考方案2】:

使用PIVOT:

SELECT *
FROM   (
  SELECT type,
         num,
         EXTRACT( MONTH FROM dt ) AS month
  FROM   table_name
)
PIVOT (
  SUM( num ) FOR month IN (
     1 AS January,
     2 AS February,
     3 AS March,
     4 AS April,
     5 AS May,
     6 AS June,
     7 AS July,
     8 AS August,
     9 AS September,
    10 AS October,
    11 AS November,
    12 AS December
  )
)

其中,对于样本数据:

CREATE TABLE table_name ( type, num, dt ) AS
SELECT 'A', 2, DATE '2015-05-15' FROM DUAL UNION ALL
SELECT 'A', 1, DATE '2015-04-15' FROM DUAL UNION ALL
SELECT 'B', 9, DATE '2015-12-03' FROM DUAL;

输出:

类型 |一月 |二月 |三月 |四月 |五月 |六月 |七月 |八月 |九月 |十月 |十一月 |十二月 :--- | ------: | --------: | ----: | ----: | ---: | ---: | ---: | -----: | --------: | ------: | --------: | --------: 乙| | | | | | | | | | | | 9 一个 | | | | 1 | 2 | | | | | | |

db小提琴here

【讨论】:

【参考方案3】:

您可以将SYS_REFCURSOR 用于存储函数中的条件聚合 SQL 语句,例如

CREATE OR REPLACE FUNCTION Get_Totals_For_Months RETURN SYS_REFCURSOR IS
  v_recordset SYS_REFCURSOR;
  v_sql       VARCHAR2(32767);
  v_cols      VARCHAR2(32767);  
BEGIN

  SELECT LISTAGG('SUM(CASE WHEN TO_CHAR("date",''mm'') = '''||LPAD(level,2,0)||
        ''' THEN "number" END ) AS 
        '||TO_CHAR(TO_DATE(LPAD(level,2,0)||'-01','mm-dd'),'Month'),',') 
           WITHIN GROUP (ORDER BY level)
    INTO v_cols
    FROM dual
 CONNECT BY level <= 12; 

  v_sql := 'SELECT type,'||v_cols||
             ' FROM tab
             GROUP BY type'; 

  OPEN v_recordset FOR v_sql;
  RETURN v_recordset;
END;
/

为了使用月份名称作为列(不考虑年份,大概只剩下一年时间

然后调用为

VAR rc REFCURSOR
EXEC :rc := Get_Totals_For_Months;
PRINT rc

【讨论】:

以上是关于如何在 Oracle SQL 中使用月份作为日期列的主要内容,如果未能解决你的问题,请参考以下文章

如何创建基于当前日期/月份动态更改列顺序的 sql 表?

如何使用 PL-SQL 在 Oracle 中获取列数据类型

在Oracle使用sql语句中如何插入日期格式的数据

ORA-01843: 无效的月份 -java 到 sql 日期转换

在 PostgreSQL 中,选择会计年度月份格式作为日期列

Oracle sql developer 日期/月份数据提取查询和语法