如何在Oracle 11g中使用with with group with group

时间:2016-04-12 16:34:07

标签: sql oracle11g

表格结构

CREATE TABLE PLAN 
  ( 
     plan_id   NUMERIC, 
     startdate DATE NOT NULL, 
     enddate   DATE, 
     cost      NUMERIC (3) NOT NULL, 
     plan_type VARCHAR (5) NOT NULL, 
     CONSTRAINT plan_pk PRIMARY KEY (plan_id), 
     CONSTRAINT plan_ck CHECK (startdate <= enddate) 
  );

要求:

创建数据透视表以按计划类型(语音,文本,数据)列出计划数量,并按成本范围列出。对于成本范围,创建3个细分,“经济计划”定义为月费低于40美元,“标准计划”定义为月费在40美元到50美元之间的计划,“保费计划”定义为月费超过40美元的计划$ 50数据透视表结果应包括3列(语音,数据,文本)和3行(经济计划,标准计划,高级计划)。单元格应该包含每个的计数,并且在没有匹配计划的情况下应该有0而不是NULL。

我的查询SO FAR

SELECT * FROM 
(SELECT cost, plan_type
    FROM plan) 
PIVOT ( count(plan_type) FOR plan_type IN ('voice', 'data', 'text')
);

它返回所有费用的语音,数据,文本类型计划的计数。我无法在要求中指定的范围内获得它。

我的其他尝试

SELECT CASE 
         WHEN cost < 40 THEN '1-40' 
         WHEN cost<=50 THEN '40-50' 
         ELSE '50+' 
       END AS cost, count('voice'), count('data'), count('text') FROM 
(SELECT cost, plan_type
    FROM plan) 
PIVOT ( 
count(plan_type) FOR plan_type IN ('voice', 'data', 'text')
)
GROUP BY CASE 
         WHEN cost < 40 THEN '1-40' 
         WHEN cost<=50 THEN '40-50' 
         ELSE '50+' 
       END;

此查询甚至从数据透视表中计算1为0值,从而返回错误的答案。请建议我该如何处理?

1 个答案:

答案 0 :(得分:1)

如果你把两次尝试结合起来,你几乎就在那里:

SELECT * FROM (
  SELECT case
           when cost < 40 then 'Economy Plans'
           when cost <= 50 then 'Standard Plans'
           else 'Premium Plans'
    end as cost_range,
    plan_type
  FROM plan
) 
PIVOT (
  count(plan_type) FOR plan_type IN ('voice' as voice, 'data' as data, 'text' as text)
);

子查询为范围分配文本标签,然后根据该范围而不是实际计划成本完成数据透视。

使用一些结果数据得出如下结果:

COST_RANGE          VOICE       DATA       TEXT
-------------- ---------- ---------- ----------
Standard Plans          1          3          0
Economy Plans           2          1          1
Premium Plans           3          2          0