Заполнить пробелы в данных - UNION, PARTITION BY или JOIN? - PullRequest
2 голосов
/ 29 марта 2010

Задача

Есть пробелы в данных, которые необходимо заполнить. Хотел бы избежать UNION или PARTITION BY, если это возможно.

Оператор запроса

Оператор выбора выглядит следующим образом:

SELECT
  count( r.incident_id ) AS incident_tally,
  r.severity_cd,
  r.incident_typ_cd
FROM
  report_vw r
GROUP BY
  r.severity_cd, r.incident_typ_cd
ORDER BY
  r.severity_cd,
  r.incident_typ_cd

Источники данных

Коды серьезности и коды типов инцидентов:

  • severity_vw
  • incident_type_vw

Столбцы:

  • incident_tally
  • severity_cd
  • incident_typ_cd

Фактические данные результата

36  0   ENVIRONMENT
1   1   DISASTER
27  1   ENVIRONMENT
4   2   SAFETY
1   3   SAFETY

Требуемые данные результата

36  0   ENVIRONMENT
0   0   DISASTER
0   0   SAFETY
27  1   ENVIRONMENT
0   1   DISASTER
0   1   SAFETY
0   2   ENVIRONMENT
0   2   DISASTER
4   2   SAFETY
0   3   ENVIRONMENT
0   3   DISASTER
1   3   SAFETY

Вопрос

Как бы вы использовали UNION, PARTITION BY или LEFT JOIN для заполнения нуля?

Ответы [ 3 ]

3 голосов
/ 30 марта 2010

Как насчет чего-то вроде

SELECT  COUNT(r.incident_id),
        crsjn.severity_cd,
        crsjn.incident_typ_cd
FROM    (
            SELECT  severity_cd,
                    incident_typ_cd
            FROM    severity_vw,
                    incident_type_vw
        ) crsjn LEFT JOIN
        report_vw r     ON  crsjn.severity_cd = r.severity_cd 
                        AND crsjn.incident_typ_cd = r.incident_typ_cd
GROUP BY crsjn.severity_cd,
        crsjn.incident_typ_cd
ORDER BY crsjn.severity_cd,
        crsjn.incident_typ_cd
1 голос
/ 30 марта 2010

Проще всего было бы, если бы в другой таблице были указаны тип и серьезность инцидента.

SELECT COALESCE(sub.incident_tally), s.severity_cd, i.incident_type_cd
FROM incident_type i
CROSS JOIN incident_severity s
LEFT JOIN (
   ... your original sql statement...
) sub ON i.incident_typ_cd = sub.incident_type_cd
  AND s.severity_cd = sub.severity_cd

И если бы у вас не было этих таблиц, вы могли бы сделать что-то подобное. Я не понимаю, почему нет ограничения UNION. Но это работает.

CREATE TYPE VARCHAR_TABLE AS TABLE OF VARCHAR2(60);
CREATE TYPE NUMBER_TABLE AS TABLE OF NUMBER;

WITH inc AS (
  SELECT /*+ CARDINALITY(nt1 3) */ column_value AS incident_type_cd
  FROM TABLE(varchar_table('ENVIRONMENT', 'DISASTER', 'SAFETY')) nt1
),
sev AS (
  SELECT /*+ CARDINALITY(nt2 4) */ column_value AS severity_cd
  FROM TABLE(number_table(0,1,2,3)) nt2
) 
SELECT *
FROM inc
CROSS JOIN sev
LEFT JOIN (
   ... your original sql statement...
) sub ON i.incident_typ_cd = sub.incident_type_cd
  AND s.severity_cd = sub.severity_cd

4

0 голосов
/ 30 марта 2010

Единственный способ, которым я могу придумать, - это далее нормализовать эту таблицу и использовать левое соединение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...