Oracle:将一些计数转换(合并)到一行?

时间:2010-01-30 22:33:02

标签: sql oracle oracle10g pivot

更新:我正在调用的内容合并我应该一直在调用 pivot

我从日志表中提取一些日常使用量。我可以轻松地将每个日期/项目的这一数据放到一行,但我想将 coalesce 的列转换为一行。

例如,我有:

date    item-to-be-counted count-of-item
10/1    foo                23
10/1    bar                45
10/2    foo                67
10/2    bar                89

我想:

date    count-of-foo     count-of-bar
10/1    23               45
10/2    67               89

这是我目前的10g查询。

select    trunc(started,'HH'),depot,count(*)
  from    logstats
 group by trunc(started,'HH'),depot
 order by trunc(started,'HH'),depot;

TRUNC(STARTED,'HH')       DEPOT      COUNT(*)
------------------------- ---------- --------
10/01/11 01.00.00         foo        28092
10/01/11 01.00.00         bar        2194
10/01/11 02.00.00         foo        3402
10/01/11 02.00.00         bar        1058

更新:11g有 pivot 操作。接受的答案显示了如何在9i和10g中执行此操作。

2 个答案:

答案 0 :(得分:4)

您正在寻找的是旋转 - 将行数据转换为柱状。

Oracle 9i +,使用WITH / CTE:


使用:

WITH summary AS (
    SELECT TRUNC(ls.started,'HH') AS dt,
           ls.depot,
           COUNT(*) AS num_depot
      FROM logstats ls
  GROUP BY TRUNC(ls.started,'HH'), ls.depot)
  SELECT s.dt,
         MAX(CASE WHEN s.depot = 'foo' THEN s.num_depot ELSE 0 END) AS "count_of_foo",
         MAX(CASE WHEN s.depot = 'bar' THEN s.num_depot ELSE 0 END) AS "count_of_bar"
    FROM summary s
GROUP BY s.dt
ORDER BY s.dt

非WITH / CTE等效


使用:

  SELECT s.dt,
         MAX(CASE WHEN s.depot = 'foo' THEN s.num_depot ELSE 0 END) AS "count_of_foo",
         MAX(CASE WHEN s.depot = 'bar' THEN s.num_depot ELSE 0 END) AS "count_of_bar"
    FROM (SELECT TRUNC(ls.started,'HH') AS dt,
                 ls.depot,
                 COUNT(*) AS num_depot
            FROM LOGSTATS ls
        GROUP BY TRUNC(ls.started, 'HH'), ls.depot) s
GROUP BY s.dt
ORDER BY s.dt

在Oracle9i之前,需要将CASE语句更改为DECODE,Oracle特定的IF / ELSE逻辑。

Oracle 11g +,使用PIVOT


未测试:

  SELECT * 
    FROM (SELECT TRUNC(ls.started, 'HH') AS dt,
                 ls.depot
            FROM LOGSTATS ls
        GROUP BY TRUNC(ls.started, 'HH'), ls.depot)
   PIVOT (
     COUNT(*) FOR depot
   )
ORDER BY 1

答案 1 :(得分:0)

好吧,我至少可以提供11解决方案;使用Pivot:

http://www.oracle.com/technology/pub/articles/oracle-database-11g-top-features/11g-pivot.html

我能想到的唯一10g选项(我对SQL很好,但不是专家)是填充表变量,然后从该表中选择单个行以获得最终结果。丑陋且可能相当慢,但可以完成工作。