我有下表,这些表包含有关文件数量和其他一些字段的信息。这是一个查找表或引用表。
我使用的oracle版本是Oracle Database 18c Enterprise E
id nm expected_num_files file_name_expr
1 CVS 3 cvs_d.*.zip
2 CVS 2 cvs_w.*.gz
3 Rite-aid 4 ra_d.*.gz
5 Walgreen 2 wal_d*.txt
我有一个审计表,其中包含收到的信息文件。这两个表都可以在 id 上加入
audit_id id file_nm
123 1 cvs_d1.zip
124 1 cvs_d2.zip
125 2 cvs_w1.gz
126 1 cvs_d3.zip
理想情况是所有文件都收到了。
理想的结果 按 id 从 auditlog 组中选择 id , count(*)
id count_files
1 3
2 2
3 4
5 2
审计表的当前结果 但在目前的情况下,我只收到了一些文件
id count_files
1 3
2 1
为了达到理想情况,我需要使用空 auditid 从查找表中填充最终表中的虚拟记录
我需要一个像这样的最终输出表。
如果我执行查询select id , count(*) from auditlog group by id
在 final table 上,我会得到上面突出显示的理想结果
audit_id id file_nm
123 1 cvs_d1.zip
124 1 cvs_d2.zip
126 1 cvs_d3.zip
-1 2 cvs_w.*.gz
125 2 cvs_w1.gz
-1 3 ra_d*.gz
-1 3 ra_d.*.gz
-1 3 ra_d.*.gz
-1 3 ra_d.*.gz
-1 5 wal_d*.txt
-1 5 wal_d*.txt
我们可以很容易地生成 initail 行,但是带有 -1 的行是根据未从列中收到的文件数生成的(他们没有发送的文件数)
解释最终表:因为我们在审计表中有 3 条记录 id 1,所以我们将它们填充到最终表中,但是对于 id 2,我们在审计表中有一个记录,我们填充了它,而对于其他记录,我们填充了 - 1.
最佳答案
至于您提供的数据,您可以按原样保留表格并创建一个 View 以根据需要提供数据:
WITH /* The following is the lookup data you provided: */
lookup(id, nm, expected_num_files, file_name_expr) AS
(SELECT 1, 'CVS', 3,'cvs_d.*.zip' from dual union all
SELECT 2, 'CVS', 2,'cvs_w.*.gz' from dual union all
SELECT 3, 'Rite-aid',4,'ra_d.*.gz' from dual union all
SELECT 5, 'Walgreen',2,'wal_d*.txt' from dual)
, /* This is the current auditlog as you described: */
auditlog(audit_id, id, file_nm) AS
(select 123, 1, 'cvs_d1.zip' from dual union all
select 124, 1, 'cvs_d2.zip' from dual union all
select 125, 2, 'cvs_w1.gz' from dual union all
select 126, 1, 'cvs_d3.zip' from dual)
, rn AS (SELECT LEVEL rn FROM dual
CONNECT BY LEVEL < (SELECT MAX(expected_num_files) FROM lookup))
/* This is the select you can put into a view: */
SELECT NVL(a.audit_id, -1) AS audit_id
, NVL(a.id,l.id) AS id
, NVL(a.file_nm, l.file_name_expr) AS file_nm
FROM lookup l
/* Create a Row for every expected file: */
JOIN rn r
ON r.rn <= l.expected_num_files
FULL JOIN (SELECT a.*
, row_number() over(PARTITION BY id ORDER BY audit_id) AS rn
FROM auditlog a) a
ON a.id = l.id
AND a.rn = r.rn
ORDER BY 2,1
结果:
AUDIT_ID | ID | FILE_NM
---------+----+-----------
123 | 1 | cvs_d1.zip
124 | 1 | cvs_d2.zip
126 | 1 | cvs_d3.zip
-1 | 2 | cvs_w.*.gz
125 | 2 | cvs_w1.gz
-1 | 3 | ra_d.*.gz
-1 | 3 | ra_d.*.gz
-1 | 3 | ra_d.*.gz
-1 | 3 | ra_d.*.gz
-1 | 5 | wal_d*.txt
-1 | 5 | wal_d*.txt
另一种编写查询的方法如下:
WITH lookup(id, nm, expected_num_files, file_name_expr) AS
(SELECT 1, 'CVS', 3,'cvs_d.*.zip' from dual union all
SELECT 2, 'CVS', 2,'cvs_w.*.gz' from dual union all
SELECT 3, 'Rite-aid',4,'ra_d.*.gz' from dual union all
SELECT 5, 'Walgreen',2,'wal_d*.txt' from dual)
, auditlog(audit_id, id, file_nm) AS
(select 123, 1, 'cvs_d1.zip' from dual union all
select 124, 1, 'cvs_d2.zip' from dual union all
select 125, 2, 'cvs_w1.gz' from dual union all
select 126, 1, 'cvs_d3.zip' from dual)
, rn AS (SELECT LEVEL rn FROM dual
CONNECT BY LEVEL < (SELECT MAX(expected_num_files) FROM lookup))
SELECT * FROM auditlog
UNION ALL
SELECT -1, l.id, l.file_name_expr
FROM lookup l
JOIN rn r
ON r.rn <= l.expected_num_files - NVL((SELECT COUNT(*) FROM auditlog WHERE id = l.id),0)
ORDER BY 2,1
关于java - 如果条件与 SQL 不匹配,则根据列生成更多行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58031164/