《Pro Oracle SQL》Chapter7 --7.6Eliminate NULLs with the GROUPING() Function

7.6 Eliminate NULLs with the GROUPING() Function  用GROUPING()函数消除NULL值  (page 207)
    There seems to be a problem with the output from the new query seen in Listing 7-12.  While the
numbers match the earlier query that used the UNION ALL operator, some of the rows have NULL values for the CUST_INCOME_LEVEL and AGE_RANGE rows, and one row has a NULL in both of these columns.  You saw this type of result earlier in Table 7-1 as an expected part of the operation of CUBE.  When generating the combinations of all columns included in the arguments to CUBE, a NULL value will be generated n-1 times for each column, where n is the number of columns in the list. In the example query, there are two columns, so you can expect to see a NULL value for CUST_INCOME_LEVEL generated once for each distinct value of AGE_RANGE. The same rule applies to the AGE_RANGE column.    
    在列表7-12中的新查询的输出似乎有点问题。虽然数量上匹配之前的使用UNION ALL运算符的查询,一些行的CUST_INCOME_LEVEL 和 AGE_RANGE 列包含NULL值,或者它们中的之一包含NULL值。你在之前的表7-1中看到过这种结果,它是CUBE运算意料之中的部分。当生成包含在CUBE参数中的所有列的组合时,对每列而言NULL值将被生成n-1次,这里n是CUBE参数列表的参数个数。 在例子查询中,有两列,这样你就能估计对于每一个AGE_RANGE的distinct值都为CUST_INCOME_LEVEL生成一个NULL值。对于AGE_RANGE列应用同样的规则。
    These NULL values* can be a problem if there are rows in the data that have NULL values for either of these columns. How do you discern between NULLs in the data and NULLs inserted by the CUBE extension?  The GROUPING() function was introduced in Oracle 8i, and it may be used to identify these superaggregate rows.  The expression used as an argument to the GROUPING() function must match an expression that appears in the GROUP BY clause.  For example, write decode(grouping(age_range),1,'ALL AGE',age_range) age_range to detect whether age_range is null due to a row generated by CUBE, or whether it is null due to a row in the database.  The value returned will be a 1 if the current row is a superaggregate row generated by CUBE, and a 0 for all other cases.    (* The NVL() function is used to provide a default value for sh.customers.cust_income_level so that output of examples may be easier to compare. )
    NULL值是个问题,如果数据行中的某些列里的数据本身就是NULL值。你如何辨别数据中的NULL值和是被CUBE扩展插入的NULL值?GROUPING()函数至从Oracle8i引入,它可用于辨别这些超聚集行。GROUPING()函数作为 表达式的 参数使用必须匹配出现在GROUP BY子句中的一个表达式。 例如,写decode(grouping(age_range),1,'ALL AGE',age_range) age_range用于检测是否age_range是因为由CUBE产生的行的null,或者是否它是因为数据库行(本身)是null。如果当前行是一个由CUBE生成的超聚集行返回的值将是1,其它情况返回的是0。 (*NVL()函数用来为sh.customers.cust_income_level提供一个默认值方便例子输出中的比较。)
    When used in combination with a CASE expression or the DECODE() function, the NULL values in
superaggregate rows can be replaced with values that are useful in a report. In this case, the DECODE() appears to be a better choice due to simplicity and the fact that there are only two possible return values for the  GROUPING() function.   Listing 7-13 shows show how GROUPING() was used to modify the SQL found in Listing 7-12. The relevant before and after parts of the SQL are shown, along with the output.  Now the report is easier to read, and superaggregate NULLs are discernable from NULLs occurring in the data. 
    当连同CASE表达式或者DECODE()函数一起使用时,在超聚集行的NULL值就能被替换成报告中有用的值了。这时候,DECODE()看起来是更好的选择因为它简单,而且事实上GROUPING()函数只有两种可能的返回值。列表7-13展示了GROUPING()是如何用于修改列表7-12中的SQL的。给出了相关SQL的前后对比,以及输出。现在报告更容易读了,超聚合的NULL值能同数据中存在的NULL值区分了。

Listing 7-13. GROUPING() Function
Without GROUPING():
 
27    , cust_income_level
28    , age_range
 
With GROUPING():
 
27    -- either CASE or DECODE() works here. I prefer DECODE() for this
28    , case grouping(cust_income_level)
29        when 1 then 'ALL INCOME'
30        else cust_income_level
31      end cust_income_level
32    , decode(grouping(age_range),1,'ALL AGE',age_range) age_range
 
QUERY                                                      AGE
TAG    PRODUCT CATEGORY               INCOME LEVEL         RANGE             PROFIT
------ ------------------------------ -------------------- -------- --------------- 
...
Q2     Hardware                       K: 250,000 - 299,999 ALL AGE       $26,678.00
Q2     Hardware                       L: 300,000 and above ALL AGE       $28,974.28
Q1     Hardware                       F: 110,000 - 129,999 70-80         $30,477.16
Q2     Hardware                       J: 190,000 - 249,999 ALL AGE       $43,761.47
Q2     Hardware                       B: 30,000 - 49,999   ALL AGE       $53,612.04
Q2     Hardware                       A: Below 30,000      ALL AGE       $55,167.88
Q2     Hardware                       I: 170,000 - 189,999 ALL AGE       $57,089.05
Q2     Hardware                       C: 50,000 - 69,999   ALL AGE       $76,612.64
Q3     Hardware                       ALL INCOME           60-70         $85,314.04
Q3     Hardware                       ALL INCOME           10-20         $90,849.87 
Q3     Hardware                       ALL INCOME           0-10          $92,207.47
Q3     Hardware                       ALL INCOME           50-60         $93,811.96
Q3     Hardware                       ALL INCOME           80-90         $95,391.82
Q2     Hardware                       H: 150,000 - 169,999 ALL AGE       $95,437.74
Q3     Hardware                       ALL INCOME           40-50         $97,492.51
Q3     Hardware                       ALL INCOME           20-30        $101,140.69
Q2     Hardware                       D: 70,000 - 89,999   ALL AGE      $102,940.44
Q3     Hardware                       ALL INCOME           30-40        $102,946.85
Q3     Hardware                       ALL INCOME           90-100       $110,310.69
Q2     Hardware                       G: 130,000 - 149,999 ALL AGE      $112,688.64
Q3     Hardware                       ALL INCOME           70-80        $117,920.88
Q2     Hardware                       E: 90,000 - 109,999  ALL AGE      $135,154.59
Q2     Hardware                       F: 110,000 - 129,999 ALL AGE      $199,270.01
Q4     Hardware                       ALL INCOME           ALL AGE      $987,386.78 

你可能感兴趣的:(oracle,sql,dba,Apress,Pro Oracle SQL)