如何在 Oracle11g 中使用 ROLLUP、RANK() 和 pivot table

How to use ROLLUP, RANK() with pivot table in Oracle11g

Table 架构

CREATE TABLE customer ( 
 id          NUMERIC, 
 lname       VARCHAR (30), 
 fname       VARCHAR (30) NOT NULL, 
 street      VARCHAR (30) NOT NULL, 
 city        VARCHAR (30) NOT NULL, 
 zipcode     NUMERIC (5) NOT NULL, 
 state       VARCHAR (2) NOT NULL, 
 phone       VARCHAR (12) NOT NULL, 
 creditscore NUMERIC, 
 credit_org  VARCHAR (30), 
 cs_date     DATE, 
 CONSTRAINT customer_pk PRIMARY KEY (id) 
);

要求:

第 1 部分: 创建一个数据透视表 table 以按位置('PA'、'CA'、'NY'、'MD')以及信用评分范围列出客户数量。对于信用分数范围,创建3个段,'LOWER RANGE(500-600)'定义为信用分数在500-600之间,'AVERAGE RANGE(600-700)'定义为信用分数在600-700之间,'PREMIUM RANGE(700+)'定义为信用分数分数700+。数据透视 table 结果应包括 4 列状态和 3 行信用评分范围。

第 2 部分: 添加总计行以给出各个州的客户总数 根据客户总数对各州进行排名。

额外要求 根据客户总数对各州进行排名,首先是高级范围,然后是平均范围,然后是较低范围。

到目前为止我的成就

SELECT * FROM (
  SELECT case
           when CREDITSCORE between 500 and 600 then 'LOWER RANGE(500-600)'
           when CREDITSCORE <= 700 then 'AVERAGE RANGE(600-700)'
           else 'PREMIUM RANGE(700+)'
    end as CREDITSCORE_RANGE,
    state
  FROM customer
) 
PIVOT (
  count(state) FOR state IN ('PA', 'CA', 'NY', 'MD')
);

第 1 部分正确

我的问题是如何解决第 2 部分,甚至可能吗?

编辑 1:

我使用 DECODE

完成以上内容

SELECT 解码(案例 当 CREDITSCORE <= 600 时 'LOWER RANGE(500-600)' 当 CREDITSCORE <= 700 时 'AVERAGE RANGE(600-700)' 否则 'PREMIUM RANGE(700+)' 结束,NULL,'TOTAL',案例 当 CREDITSCORE 在 500 和 600 之间时 'LOWER RANGE(500-600)' 当 CREDITSCORE <= 700 时 'AVERAGE RANGE(600-700)' 否则 'PREMIUM RANGE(700+)' 结束) "CREDITSCORE_RANGE", SUM(解码(状态, 'PA', 1, 0)) "Pennsylvania", SUM(解码(状态, 'CA', 1, 0)) "California", SUM(解码(状态, 'NY', 1, 0)) "New York", SUM(解码(状态, 'MD', 1, 0)) "Maryland", 计数(信用分数)"Total No of Customers", RANK() OVER (ORDER BY Count(CREDITSCORE) DESC) "RANK BY NO OF CUSTOMERS" 来自客户 GROUP BY ROLLUP(案例 当 CREDITSCORE 在 500 和 600 之间时 'LOWER RANGE(500-600)' 当 CREDITSCORE <= 700 时 'AVERAGE RANGE(600-700)' 否则 'PREMIUM RANGE(700+)' 结束);

我认为您的范围不太适合您所写的查询,尽管作业的措辞含糊不清,因为 'between' 是包容性的 - 因此问题的措辞是信用评分'lower' 和 'average' 括号中都会出现 600 个。您的版本会将 600 放在 'lower' 括号中,但应该放在哪个括号中值得商榷;我认为它应该是 'average' 从其他定义,但目前还不清楚。分数低于 500 的问题中没有括号,但如果您有任何分数,那么您当前的代码会将它们包含在 'average' 括号中,因为它们小于 700 但不在 500 到 600 之间。

所以我将其解释为:

SELECT * FROM (
  SELECT case
           when CREDITSCORE >= 500 and CREDITSCORE < 600 then 'LOWER RANGE(500-600)'
           when CREDITSCORE >= 600 and CREDITSCORE < 700 then 'AVERAGE RANGE(600-700)'
           when CREDITSCORE >= 700 then 'PREMIUM RANGE(700+)'
    end as CREDITSCORE_RANGE,
    state
  FROM customer
) 
PIVOT (
  count(state) FOR state IN ('PA' as pa, 'CA' as ca, 'NY' as ny, 'MD' as md)
);

您的问题标题是指 ROLLUP,要获取总行数,您可以使用该函数:

SELECT creditscore_range, sum(pa) AS pa, sum(ca) AS ca, sum(ny) AS ny, sum(md) AS md
FROM (
  SELECT * FROM (
    SELECT CASE
             WHEN creditscore >= 500 AND creditscore < 600 THEN 'LOWER RANGE(500-600)'
             WHEN creditscore >= 600 AND creditscore < 700 THEN 'AVERAGE RANGE(600-700)'
             WHEN creditscore >= 700 THEN 'PREMIUM RANGE(700+)'
      END AS creditscore_range,
      state
    FROM customer
  ) 
  PIVOT (
    COUNT(state) FOR state IN ('PA' AS pa, 'CA' AS ca, 'NY' AS ny, 'MD' AS md)
  )
)
GROUP BY ROLLUP (creditscore_range);

如果您的分数确实低于 500,那么 Both 都会为那些 creditscore_range 为空的分数添加一行;这与 ROLLUP 版本混淆。您可能希望从最里面的查询中过滤掉任何小于 500 的分数,但同样不清楚是否有必要或需要这样做。

我不确定作业在谈到排名时是否在寻找。这意味着根据它们包含的值更改列顺序。如果数据以其他方式旋转,则按州排名会更有意义。