如何显示每个月的总利润,当该月在oracle中没有记录时显示null

时间:2019-11-03 10:37:19

标签: sql oracle oracle11g

我正在生成一份报告,显示2018年每个月的总利润,当某些月份没有利润时显示NIL

获得的利润= 0.1 *总付款。 服务完成后赚取利润,表格“ BOOKING”中的“ Total_payment”列来自我,我必须加入BOOKING和SERVICE才能获得每个月的总利润,Booking_num是加入BOOKING和SERVICE的关键, Actual_end是服务的结束日期

现在的问题是,1月,2月和8月没有利润。 反正这三个月的利润栏中有没有显示NIL?

SELECT EXTRACT(MONTH FROM Actual_end) AS MONTH,SUM(Total_payment *0.1) AS PROFIT
FROM SERVICE,BOOKING
WHERE SERVICE.Booking_num = BOOKING.Booking_num
AND EXTRACT(YEAR FROM Actual_end) = 2018
GROUP BY EXTRACT(MONTH FROM Actual_end);

这是显示9个月没有jan,feb和aug的利润的代码

MONTH  PROFIT
3      88.4
4      146.1
5      112.6
6      108.3
7      102.6
9      130.3
10     72.6
12     124.9

我希望输出是

MONTH    PROFIT
1        NIL
2        NIL
3        88.4
4        146.1 
5        112.6
6        108.3
7        102.6
8        NIL
9        130.3
10       72.6
11       124.9
12       25.2

我如何进行修改,我也尝试过

WITH CALENDAR AS(
SELECT TO_CHAR(add_months(date '2018-01-01',ROWNUM -1),'MM') AS MONTH
FROM DUAL
CONNECT BY LEVEL <=12)
SELECT CALENDER.MONTH, NVL(SUM(Total_payment*0.1),null) AS PROFIT
FROM BOOKING,SERVICE,CALENDER
WHERE BOOKING.Booking_num = SERVICE.Booking_num
AND CALENDER.MONTH = EXTRACT(MONTH FROM Actual_end(+))
AND EXTRACT(MONTH FROM Actual_end) = 2018
GROUP BY CALENDER.MONTH

输出: 没有选择行

2 个答案:

答案 0 :(得分:2)

您需要和外部联接(左或右)。顺便说一句,摆脱表之间的老式逗号分隔联接,而是使用显式联接。

如果要返回整年的某一年是一个问题,请在查询中添加RIGHT JOIN (SELECT LEVEL AS MNT FROM DUAL CONNECT BY LEVEL <= 12 ) MNT

SELECT MNT AS MONTH,NVL(TO_CHAR(SUM(Total_payment *0.1)),'NIL') AS PROFIT
  FROM SERVICE S
  JOIN BOOKING B
    ON S.Booking_num = B.Booking_num
 RIGHT JOIN (SELECT LEVEL AS MNT 
               FROM DUAL 
             CONNECT BY LEVEL <= 12 ) MNT
         ON MNT.MNT = EXTRACT(MONTH FROM Actual_end) 
           AND EXTRACT(YEAR FROM Actual_end)=2018                     
GROUP BY MNT
ORDER BY MONTH;

Demo

答案 1 :(得分:0)

在这种情况下,您需要列出所有月份:

with months as (
      select 1 as month from dual union all
      select 2 as month from dual union all
      select 3 as month from dual union all
      select 4 as month from dual union all
      select 5 as month from dual union all
      select 6 as month from dual union all
      select 7 as month from dual union all
      select 8 as month from dual union all
      select 9 as month from dual union all
      select 10 as month from dual union all
      select 11 as month from dual union all
      select 12 as month from dual
     )
select m.month, sum(s.total_payment * 0.1) as profit
from months m left join
     booking b
     on extract(month from b.actual_end) = m.month and
        b.actual_end >= date '2018-01-01' and
        b.actual_end < date '2019-01-01' left join
     service s join
     on s.booking_num = b.booking_num 
group by m.month;

注意:

  • 这猜测actual_endbooking中,而total_paymentservice中。如果此猜测不正确,则查询会稍有不同。
  • 从不FROM子句中使用逗号。
  • 此查询应使用LEFT JOIN。第一个表具有所需的所有行。
  • 后续表中的过滤器放在on子句中,而不是where子句中。
  • 请注意日期常量的使用。这种比较通常使引擎更容易优化查询(通常通过使用索引)。