填补数据空白 - UNION,PARTITION BY或JOIN?

时间:2010-03-29 19:58:37

标签: sql oracle oracle11g

问题

需要填补数据空白。如果可能,请避免UNIONPARTITION BY

查询声明

select语句如下:

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

问题

您如何使用UNIONPARTITION BYLEFT JOIN填写零点数?

3 个答案:

答案 0 :(得分:3)

这样的东西
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 :(得分:1)

最容易的是,如果您在另一个表中有事件类型和事件严重性。

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

答案 2 :(得分:0)

我能想到的唯一方法是进一步规范化该表并使用左连接。