如何从现有 table 条记录创建视图,同时添加不存在的新记录

How to create a view from existing table records, but also adding new records that do not exist

我正在尝试从现有视图数据创建视图,但如果每个 part/date 组合中有某些行不存在,则创建这些行。我有以下查询,显示了我目前对特定 s_date/part_no 组合的查询:

SELECT
    s_date,
    part_no,
    issue_group,
    s_level,
    qty_filled
FROM
    current_view
WHERE
    part_no = 'xxxxx'
    AND s_date IN (
        '201802',
        '201803'
    )
ORDER BY
    s_date,
    part_no,
    issue_group,
    DECODE(s_level, '80', 1, '100', 2, 'Late', 3)

产生以下内容:

我知道如何使用该数据创建视图,这是最简单的部分。但我需要的是每个 issue_group and s_level 组合一行,如果它是创建的行,则将 0 作为 qty_filled

每个 part_no / s_date 组合应该有 6 行

 - issue_group = '1' / s_level = '80'
 - issue_group = '1' / s_level = '100'
 - issue_group = '1' / s_level = 'Late'
 - issue_group = '2/3 ' / s_level = '80'
 - issue_group = '2/3 ' / s_level = '100'
 - issue_group = '2/3 ' / s_level = 'Late'

因此,如果当前 s_date/part_no 已经存在上述组合之一,那么它显然会从当前视图中获取 qty_filled 信息。如果不是,则创建一个新行,并且 qty_filled = 0。所以我试图让它看起来像这样:

我只展示了 1 个部分,有几个日期,只是为了说明问题。 table 中有 10k+ 个部分,6 个 issue_group/s_level 组合中的每个组合都不会超过 1 个 part/date 组合。

一个解决方案可能是使用(固定)值列表之间的笛卡尔积生成所有预期行的笛卡尔积,然后 LEFT JOIN 它与 current_view

以下查询保证您将获得每个给定 s_date/part_no/issue_group/s_level 元组的记录。如果 current_view 中没有记录匹配,查询将显示 0 个数量。

SELECT
    sd.s_date,
    pn.part_no,
    ig.issue_group,
    sl.s_level,
    COALESCE(cv.qty_filled, 0) qty_filled
FROM
    (SELECT '201802' AS s_date UNION SELECT '201803') AS sd
    CROSS JOIN (SELECT 'xxxxx' AS part_no) AS pn
    CROSS JOIN (SELECT '1' AS issue_group UNION SELECT '2') AS ig
    CROSS JOIN (SELECT '80' AS s_level UNION SELECT '100' UNION SELECT 'Late') AS sl
    LEFT JOIN current_view cv 
        ON  cv.s_date      = sd.s_date
        AND cv.part_no     = pn.part_no
        AND cv.issue_group = ig.issue_group
        AND cv.s_level     = ig.s_level
ORDER BY
    sd.s_date,
    pn.part_no,
    ig.issue_group,
    DECODE(sl.s_level, '80', 1, '100', 2, 'Late', 3)

注意:您没有标记 RDBMS。这应该适用于大多数,除了 Oracle,您需要在列出允许值的查询中向每个 select 添加 FROM DUAL,例如:

(SELECT '201802' AS s_date FROM DUAL UNION SELECT '201803' FROM DUAL) AS sd

想法是使用 CROSS JOIN 生成行,然后使用 LEFT JOIN 引入额外信息。在 Oracle 语法中,这看起来像:

WITH v as (
      SELECT v.*
      FROM current_view v
      WHERE part_no = 'xxxxx' AND
            s_date IN ('201802', '201803')
    )
SELECT d.s_date, ig.part_no, ig.issue_group, l.s_level,
       COALESCE(v.qty_filled, 0) as qty_filled
FROM (SELECT DISTINCT s_date FROM v) d CROSS JOIN
     (SELECT DISTINCT part_no, ISSUE_GROUP FROM v) ig CROSS JOIN
     (SELECT '80' as s_level FROM DUAL UNION ALL
      SELECT '100' FROM DUAL UNION ALL
      SELECT 'LATE' FROM DUAL
     ) l LEFT JOIN
     v
     ON v.s_date = d.s_date AND v.part_no = ig.part_no AND
        v.issue_group = ig.issue_group AND v.s_level = l.s_level
ORDER BY s_date, part_no, issue_group,
         (CASE s_level WHEN  '80' THEN 1 WHEN '100' THEN 2 WHEN 'Late' THEN 3 END)