• Aucun résultat trouvé

Generatin�� reports with only summary rows

Dans le document Oracle Business Intelligence: (Page 68-72)

In some cases, you may not need to include the rows that represent the subtotals generated by GROUPBY, but include only the total rows. This is where the GROUPING SETS extension of the GROUPBY clause may come in handy:

SELECT r.reg_name region, TO_CHAR(TO_DATE(EXTRACT(MONTH FROM (o.orddat e)),'MM'),'Month') month, SUM(o.total) sales

FROM regions r, orders o WHERE r.reg_id = o.regid

GROUP BY GROUPING SETS(r.reg_name, EXTRACT(MONTH FROM (o.orddate)));

This query should produce the following report:

REGION MONTH SALES

You receive an interesting result when performing a partial GROUPINGSET operation like the one shown next:

SELECT r.reg_name region, TO_CHAR(TO_DATE(EXTRACT(MONTH FROM (o.orddat e)),'MM'),'Month') month, SUM(o.total) sales

FROM regions r, orders o

[ 58 ] This should give you the following results:

REGION MONTH SALES

It's interesting to note that the above report doesn't include summary rows—neither for each month nor for each region. Instead, it shows you all those subtotal rows generated by GROUPBY and excluded from the full GROUPINGSET operation discussed earlier in this section. In this sense, a partial GROUPINGSET operation is a reverse operation to the corresponding full one.

Rankin��

Looking back to Chapter 1, you might recall the discussion on the problem of finding the top three salespersons, in the Asking business questions using data-access tools section. In that example, you used the RANK analytic SQL function to compute the rank of each salesperson, based on their sales.

Turning back to the data structures discussed in this chapter, you might, for example, compose a query that will compute a rank for each region, based on the sales figures. To better understand how ranking works, though, let's first look at the query that simply summarizes sales figures per region:

SELECT r.reg_name region, SUM(o.total) sales FROM regions r, orders o

WHERE r.reg_id = o.regid

GROUP BY GROUPING SETS(r.reg_name);

Here is the output you should see:

REGION SALES ---North America 17880 Europe 6310.5

www.it-ebooks.info

Now let's look at the query that will compute a sales rank for each region in ascending order:

SELECT r.reg_name region, SUM(o.total) sales, RANK() OVER (ORDER BY SUM(o.total) ASC) rank

FROM regions r, orders o WHERE r.reg_id = o.regid

GROUP BY GROUPING SETS(r.reg_name);

This time, the query results should look like this:

REGION SALES RANK ---Europe 6310.5 1 North America 17880 2

As you can see in the above rows, not only are region sales arranged in ascending order, but the rank column has also appeared. If you don't want to see the rank column, you might remove it from the select list and add the ORDERBY clause with the rank function, rewriting the query as follows:

SELECT r.reg_name region, SUM(o.total) sales FROM regions r, orders o

WHERE r.reg_id = o.regid

GROUP BY GROUPING SETS(r.reg_name)

ORDER BY RANK() OVER (ORDER BY SUM(o.total) ASC);

This should produce the following output:

REGION SALES ---Europe 6310.5 North America 17880

As you can see, a little trick of moving the rank function from the select list to the ORDERBY clause lets you exclude the ranking column from the output, keeping sales figures in the sales column arranged in ascending order.

[ 60 ]

Windowin��

Windowing functions make up another important group of analytic SQL functions.

The idea behind windowing functions is that they enable aggregate calculations to be made within a "sliding window" that may float down as you proceed through the result set. For example, you might want to include a slidingaverage column in the report containing total monthly sales. This column would contain the average sales for each row, based on the sales figures in the preceding, current, and following rows. Thus, the average for the January row will be calculated based on the value of the sales field in the January row, as well as the value of the sales field in the February row. In turn, the average for the February row will be determined using the sales field's values throughout all three rows. Finally, the average for the March row will be computed based on the sales for February and March.

The following diagram gives a graphical illustration of this example:

Let's first look at the query that simply calculates total monthly sales, which should look like this:

SELECT TO_CHAR(TO_DATE(EXTRACT(MONTH FROM (o.orddate)),'MM'),'Month') month, SUM(o.total) sales

FROM orders o

GROUP BY TO_CHAR(TO_DATE(EXTRACT(MONTH FROM (o.orddate)),'MM'),'Month ');

Here is the output:

MONTH SALES --- ---January 5240 February 5550 March 13400.5

www.it-ebooks.info

Now let's modify the query and define a "window" that will float down the above rows, calculating a value for the sliding_avg field. In the following query, note the use of the ROWSBETWEEN clause, and the keywords 1PRECEDING and 1FOLLOWING defining the parameters of the sliding window:

SELECT TO_CHAR(TO_DATE(EXTRACT(MONTH FROM (o.orddate)),'MM'),'Month') month, SUM(o.total) sales,

AVG(SUM(o.total)) OVER (ORDER BY TO_CHAR(TO_DATE(EXTRACT(MONTH FROM (o.orddate)),'MM'),'Month') ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) sliding_avg

FROM orders o

GROUP BY TO_CHAR(TO_DATE(EXTRACT(MONTH FROM (o.orddate)),'MM'),'Month ');

The output should look like the following:

MONTH SALES SLIDING_AVG --- --- ---February 5550 5395 January 5240 8063.5 March 13400.5 9320.25

Aside from the AVG function, you can apply the windowing technique using the other aggregate functions, such as SUM, MIN, and MAX.

Dans le document Oracle Business Intelligence: (Page 68-72)