如何在 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 中使用月份作为日期列的主要内容,如果未能解决你的问题,请参考以下文章
ORA-01843: 无效的月份 -java 到 sql 日期转换