2017-03-07 72 views
-1

我想用兩個表進行查詢。即使表格中沒有記錄,我也想顯示用戶所選年份的所有月份。不過,我無法顯示所有的月份,也沒有空值。請幫忙?如何在oracle中選擇用戶選擇年份的所有月份

這裏是我的查詢:

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

方法。 com/node/2029 –

+0

而您正在尋找的搜索詞是「日曆表」或「日曆視圖」。 –

+0

[如何在Oracle中填充日曆表?](http://stackoverflow.com/questions/8374959/how-to-populate-calendar-table-in-oracle) –

回答

0

使用PARTITION加入:

甲骨文設置

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 
) 
); 

輸出:HTTP://www.orafaq使用`DBA_TABLES`以產生足夠的行

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 
+0

它給c.MONTH無效標識符錯誤... –

+1

@ T.Rifle查詢不會給我一個錯誤;請檢查您是否已正確複製。我還添加了一個與您的更新報告格式相匹配的更新。今後請(a)首先提出完整的問題,而不是在出現[XY-problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)解決方案和(b)不會如此戲劇性地更改您的問題輸出,因爲這會使一些答案失效。 – MT0

+0

感謝您的回答。查詢2對我很好。 –

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 
+0

感謝您的答案,但它給出了相同的結果。即使他們有空值,我也想顯示所有月份。 –

+0

我剛修改了查詢:請再試一次。如果它仍然不起作用,您需要發佈一些示例數據。 – APC