【问题标题】:How to show total profit for each month, show null when there is no record in that month in oracle如何显示每个月的总利润,当oracle中当月没有记录时显示null
【发布时间】:2019-11-04 06:44:38
【问题描述】:

我正在制作一份报告以显示 2018 年每个月的总利润,并在某些月份没有赚取利润时显示 NIL

赚取的利润 = 0.1 * Total_payment。 服务完成后赚取利润,“Total_payment”列来自表BOOKING,我必须加入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个月利润的代码,没有一月,二月和八月

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

输出: 未选择任何行

【问题讨论】:

  • 您需要制作一个称为日历表的东西或使用交付的表(我相信 oracle 在手册中将其称为内联视图),但不是存储日期,而是存储月份的数字。 . 将数据与该日历表或交付表在月份数上左连接时,您将获得这些缺失值NULL
  • 限定列名,以便清楚列的来源!

标签: sql oracle oracle11g


【解决方案1】:

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

如果返回某一年和整月是问题,请将RIGHT JOIN (SELECT LEVEL AS MNT FROM DUAL CONNECT BY LEVEL &lt;= 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

【讨论】:

    【解决方案2】:

    在这种情况下,您需要一个所有月份的列表:

    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 子句中。
    • 注意日期常量的使用。这种比较通常使引擎更容易优化查询(通常通过使用索引)。

    【讨论】:

    • 但是当月没有利润时,如何在利润栏中显示NIL?
    • @fayelan 。 . .此查询应显示NULL,这是 SQL 在这种情况下所做的。
    猜你喜欢
    • 1970-01-01
    • 2019-12-23
    • 2023-04-04
    • 2021-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多