我正在尝试使用两个表进行查询。即使表中没有记录,我也希望显示用户选定年份的所有月份。但是我无法显示所有月份,也没有显示空值。请帮帮忙?
这是我的问题:
SELECT spendList.NUMBER,
spendList.User,
TO_CHAR(spendList.DATE, 'Month') as Month,
spendList.AMOUNT, allowence.FUND
FROM T_EXPENDITURE spendList
LEFT JOIN T_ALLOWENCE allowence
ON spendList.DEP_NO = allowence.DEP_NO
WHERE TO_CHAR(spendList.DATE, 'YYYY') = :userYear
ORDER BY spendList.DEPARTMENT
结果必须如下:
NUMBER USER MONTH SPEND_AMOUNT ALLOWENCE
12345 Clerk January 123 2500
7869 Manager February 150 3000
12345 Clerk March 2500
7869 Manager April 3000
12345 Clerk May 2500
7869 Manager June 3000
12345 Clerk July 2500
7869 Manager August 3000
12345 Clerk September 2500
7869 Manager September 3000
12345 Clerk October 2500
7869 Manager Nevember 3000
12345 Clerk December 2500
我会在报告中使用此结果,在报告中可能会出现一年中的所有月份。
报告就像:
NUMBER USER January February ... December ALLOWENCE
12345 Clerk 123 null null 2500
答案 0 :(得分:1)
此解决方案使用WITH子句语法生成一年中所有月份的子查询(技术上是每个月的第一天)。它假定:userYear
作为一个四位数字传递给一个日期,然后用yyyy
掩码截断以获得一年的第一天。 add_months()
用于获取剩余的月份。
通过派生每条记录的第一天,此子查询外部连接到您的T_EXPENDITURE表。
with calendar as (
select add_months(trunc(to_date(:userYear,'yyyy'),'yyyy'), level-1) as mon
from dual
connect by level <=12)
SELECT to_char(calendar.mon,'MONTH') as Month,
spendList.NUMBER,
spendList.User,
spendList.AMOUNT,
allowence.FUND
FROM calendar
left join T_EXPENDITURE spendList
on trunc(spendList.DATE, 'MON') = calendar.mon
LEFT JOIN T_ALLOWENCE allowence
ON spendList.DEP_NO=allowence.DEP_NO
ORDER BY spendList.DEPARTMENT
答案 1 :(得分:0)
使用PARTITION
加入:
Oracle安装程序:
CREATE TABLE T_EXPENDITURE ( "NUMBER", "USER", "DATE", amount, dep_no ) AS
SELECT 1, 'Clerk', DATE '2017-01-10', 50, 1 FROM DUAL UNION ALL
SELECT 1, 'Clerk', DATE '2017-01-15', 73, 1 FROM DUAL UNION ALL
SELECT 1, 'Clerk', DATE '2017-02-14', 13, 1 FROM DUAL UNION ALL
SELECT 2, 'Manager', DATE '2017-02-01', 150, 2 FROM DUAL;
CREATE TABLE T_ALLOWENCE ( dep_no, fund ) AS
SELECT 1, 2500 FROM DUAL UNION ALL
SELECT 1, 3000 FROM DUAL;
<强>查询强>:
SELECT e."NUMBER",
e."USER",
c.month,
SUM( e.amount ) AS amount,
e.fund
FROM
(
SELECT e.*, a.fund
FROM t_allowance a
INNER JOIN t_expenditure e
ON ( e.dep_no = a.dep_no )
) e
PARTITION BY ( e."NUMBER", e."USER", e.FUND )
RIGHT OUTER JOIN
(
SELECT ADD_MONTHS( TO_DATE( :useryear || '0101', 'YYYYMMDD' ), LEVEL - 1 ) AS month
FROM DUAL
CONNECT BY LEVEL <= 12
) c
ON( c.month <= e."DATE" AND e."DATE" < ADD_MONTHS( c.month, 1 ) )
GROUP BY e."NUMBER", e."USER", e.FUND, c.MONTH
ORDER BY e."NUMBER", c.MONTH;
<强>输出强>:
NUMBER USER MONTH AMOUNT FUND
------ ------- ---------- ------ ----
1 Clerk 2017-01-01 123 2500
1 Clerk 2017-02-01 13 2500
1 Clerk 2017-03-01 2500
1 Clerk 2017-04-01 2500
1 Clerk 2017-05-01 2500
1 Clerk 2017-06-01 2500
1 Clerk 2017-07-01 2500
1 Clerk 2017-08-01 2500
1 Clerk 2017-09-01 2500
1 Clerk 2017-10-01 2500
1 Clerk 2017-11-01 2500
1 Clerk 2017-12-01 2500
2 Manager 2017-01-01 3000
2 Manager 2017-02-01 150 3000
2 Manager 2017-03-01 3000
2 Manager 2017-04-01 3000
2 Manager 2017-05-01 3000
2 Manager 2017-06-01 3000
2 Manager 2017-07-01 3000
2 Manager 2017-08-01 3000
2 Manager 2017-09-01 3000
2 Manager 2017-10-01 3000
2 Manager 2017-11-01 3000
2 Manager 2017-12-01 3000
查询2 :
SELECT *
FROM (
SELECT "NUMBER",
"USER",
EXTRACT( MONTH FROM "DATE" ) AS month,
amount,
e.dep_no,
fund
FROM T_EXPENDITURE e
INNER JOIN T_ALLOWENCE a
ON ( e.dep_no = a.dep_no )
WHERE EXTRACT( YEAR FROM e."DATE" ) = :useryear
)
PIVOT (
SUM( amount )
FOR month IN (
1 AS Jan, 2 AS Feb, 3 AS Mar, 4 AS Apr, 5 AS May, 6 AS Jun,
7 AS Jul, 8 AS Aug, 9 AS Sep, 10 AS Oct, 11 AS Nov, 12 AS Dec
)
);
<强>输出强>:
NUMBER USER DEP_NO FUND JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
------ ------- ------ ---- --- --- --- --- --- --- --- --- --- --- --- ---
1 Clerk 1 2500 123 13
2 Manager 2 3000 150