如何从现有 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)
我正在尝试从现有视图数据创建视图,但如果每个 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)