如何在oracle

时间:2017-03-07 07:52:52

标签: sql 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

2 个答案:

答案 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