在oracle sql中聚合多个列

时间:2016-04-20 16:52:42

标签: oracle oracle11g pivot

很难说出这个问题。如果有更好的标题,请告诉我。

我有一个产生如下数据的查询:

 def show(x: Option[String]) = x match {
     case Some(s) if(s.head.isUpper) => s
     case None     => "No value"
 } 

或者,我可以生成这样的数据:

+----------+----------+----------+----------+----------+
|   KEY    | FEB_GRP1 | JAN_GRP1 | FEB_GRP2 | JAN_GRP2 |
+----------+----------+----------+----------+----------+
| 50840992 |        1 |        1 |        0 |        0 |
| 50840921 |        0 |        1 |        1 |        0 |
| 50848995 |        0 |        0 |        0 |        0 |
+----------+----------+----------+----------+----------+

其中< 50应该反击"第1组"和〜< 50应该作为"组2"。

我希望它是这样的:

+----------+------+------+
|   KEY    | JAN  | FEB  |
+----------+------+------+
| 50840992 | <50  | ~<50 |
| 50840921 | <50  | <50  |
| 50848995 | ~<50 | ~<50 |
| 50840885 | <50  | <50  |
+----------+------+------+

我只能通过对JAN_GRP1求和得到JAN_GRP1_SUM,但我希望它只是一个数据点,而不是列本身。

我的查询(生成第一张图):

+-------+------+------+
| MONTH | GRP1 | GRP2 |
+-------+------+------+
| JAN   |    2 |    0 |
| FEB   |    1 |    1 |
+-------+------+------+

1 个答案:

答案 0 :(得分:2)

您的数据模型没有多大意义,但从您展示的内容中可以做到:

select 'JAN' as month,
  count(case when "JAN-1-2016" = '<50' then 1 end) as grp1,
  count(case when "JAN-1-2016" != '<50' then 1 end) as grp2
from my_table
union all
select 'FEB' as month,
  count(case when "FEB-1-2016" = '<50' then 1 end) as grp1,
  count(case when "FEB-1-2016" != '<50' then 1 end) as grp2
from my_table;

这不能很好地扩展 - 如果你有更多的月份需要为每一个添加另一个联合分支。

如果您的查询基于视图或之前计算的摘要,那么返回原始数据可能会容易得多。

如果你坚持这一点,那么另一种可能的方法,如果你实际上有两个多月的时间可能会更容易管理,可能是取消数据的转移:

select *
from my_table
unpivot(value for month in ("JAN-1-2016" as date '2016-01-01',
  "FEB-1-2016" as date '2016-02-01') --, etc. for other months
);

然后聚合:

select to_char(month, 'MON', 'NLS_DATE_LANGUAGE=ENGLISH') as month,
  count(case when value = '<50' then 1 end) as grp1,
  count(case when value != '<50' then 1 end) as grp2
from (
  select *
  from my_table
  unpivot(value for month in ("JAN-1-2016" as date '2016-01-01',
    "FEB-1-2016" as date '2016-02-01') --, etc. for other months
  )
)
group by month;

仍然不是很漂亮,Oracle在我认为的内容中做了几乎相同的事情,但是创建和维护的案例表达式更少 - 苦差事部分是非对话。您可能需要在“月份”字段中包含年份,具体取决于您拥有的数据范围。