简体   繁体   中英

Oracle SQL Help Data Totals

I am on Oracle 12c and need help with the simple query.

Here is the sample data of what I currently have:

Table Name: customer

Table DDL

create table customer(
    customer_id    varchar2(50),
    name           varchar2(50),
    activation_dt  date,
    space_occupied number(50)
    );

Sample Table Data:

customer_id  name     activation_dt  space_occupied 
abc          abc-001  2016-09-12                 20
xyz          xyz-001  2016-09-12                 10

Sample Data Output

The query I am looking for will provide the following:

customer_id  name     activation_dt  space_occupied
abc          abc-001  2016-09-12                 20
xyz          xyz-001  2016-09-12                 10
Total_Space  null     null                       30

Here is a slightly hack-y approach to this, using the grouping function ROLLUP() . Find out more .

SQL> select coalesce(customer_id, 'Total Space') as customer_id
  2         , name
  3        , activation_dt
  4        , sum(space_occupied) as space_occupied
  5  from customer
  6  group by ROLLUP(customer_id, name, activation_dt)
  7  having grouping(customer_id) = 1
  8  or (grouping(name) + grouping(customer_id)+ grouping(activation_dt)) = 0;

CUSTOMER_ID  NAME         ACTIVATIO SPACE_OCCUPIED
------------ ------------ --------- --------------
abc          abc-001      12-SEP-16             20
xyz          xyz-001      12-SEP-16             10
Total Space                                     30

SQL> 

ROLLUP() generates intermediate totals for each combination of column; the verbose HAVING clause filters them out and retains only the grand total.

What you want is a bit unusual, as if customer_id is integer, then you have to cast it to string etc, but it this is your requirement, then if be achieved this way.

SELECT customer_id,
       name,
       activation_dt,
       space_occupied
FROM
  (SELECT   1   AS seq,
                customer_id,
                name,
                activation_dt,
                space_occupied
   FROM customer

    UNION ALL 

   SELECT 2             AS seq,
    'Total_Space'       AS customer_id,
    NULL                AS name,
    NULL                AS activation_dt,
    sum(space_occupied) AS space_occupied
   FROM customer
   )
ORDER BY seq

Explanation:

  • Inner query:
    • First part of union all; I added 1 as seq to give 1 hardcoded with your resultset from customer.
    • Second part of union all: I am just calculating sum(space_occupied) and hardcoding other columns, including 2 as seq
  • Outer query; Selecting the data columns and order by seq, so Total_Space is returned at last.

Output

    +-------------+---------+---------------+----------------+
    | CUSTOMER_ID |  NAME   | ACTIVATION_DT | SPACE_OCCUPIED |
    +-------------+---------+---------------+----------------+
    | abc         | abc-001 | 12-SEP-16     |             20 |
    | xyz         | xyz-001 | 12-SEP-16     |             10 |
    | Total_Space | null    | null          |             30 |
    +-------------+---------+---------------+----------------+

Seems like a great place to use group by grouping sets seems like this is what they were designed for. Doc link

SELECT coalesce(Customer_Id,'Total_Space') as Customer_ID
     , Name
     , ActiviatioN_DT
     , sum(Space_occupied) space_Occupied
FROM customer
GROUP BY GROUPING SETS ((Customer_ID, Name, Activation_DT, Space_Occupied)
                       ,())

The key thing here is we are summing space occupied. The two different grouping mechanisms tell the engine to keep each row in it's original form and 1 records with space_occupied summed; since we group by () empty set; only aggregated values will be returned; along with constants (coalesce hardcoded value for total!)

在此处输入图片说明

The power of this is that if you needed to group by other things as well you could have multiple grouping sets. imagine a material with a product division, group and line and I want a report with sales totals by division, group and line. You could simply group by () to get grand total, (product_division, Product_Group, line) to get a product line (product_Divsion, product_group) to get a product_group total and (product_division) to get a product Division total. pretty powerful stuff for a partial cube generation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM