Oracle: pivot (coalesce) рассчитывает на один ряд? - PullRequest
4 голосов
/ 31 января 2010

обновление: то, что я звонил объединение Я должен был звонить пивот .

Я извлекаю некоторые ежедневные данные об использовании из таблицы журнала. Я легко могу получить эти данные по одной строке на дату / элемент, но я бы хотел объединить объединить столбцов в одну строку.

Например, у меня есть:

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 ]

4 голосов
/ 31 января 2010

То, что вы ищете, это поворот - перенос данных строки в столбчатые.

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

Эквивалент без СО / СТЕ


Использование:

  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
0 голосов
/ 31 января 2010

Ну, я могу по крайней мере предоставить решение 11; используйте Pivot:

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

Единственный вариант 10g, который я могу придумать неординарно (я хорошо разбираюсь в SQL, но не эксперт), - это заполнить переменную таблицы и затем выбрать отдельные строки из этой таблицы для вашего окончательного результата. Уродливый и, вероятно, довольно медленный, но может сделать работу.

...