我有一张有事故的大桌子。有了这个,我想附加事件附件和事件注释中的值。我使用了左外连接,因为事件可能有也可能没有任何意见或附件 现在当我使用多个外连接时,我得到重复的行。
所有表格都有一个commonID值
INC1 ATT1 COMMENT1
INC1 ATT1 COMMENT2
INC1 ATT2 COMMENT1
INC1 ATT2 COMMENT2
但实际上输出应该是:
INC1 ATT1 COMMENT1
INC1 ATT2 COMMENT2
以便在将自己附加到事件表时附件和注释值是独立的。
select inc,att.attname,comment.commenttext
from inc
left outer join att inc.incidentID=att.incidentID
left outer join comment inc.incidentID=comment .incidentID
这可能吗?
答案 0 :(得分:2)
到目前为止,我从你的回答中得到的一点是,对于某一特定事件,其附件与其评论之间没有直接关系。 如果我理解正确,您希望将事件视为附件和注释的简单“容器”,并且您只需要列出每个事件。哪一个 附件恰好出现在同一行中,因为特定评论是偶然发生的。
测试数据:
SQL> CREATE TABLE inc (incidentid NUMBER, incname VARCHAR2(20));
Table created.
SQL> INSERT INTO inc VALUES (1,'incident 1');
1 row created.
SQL> INSERT INTO inc VALUES (2,'incident 2');
1 row created.
SQL> CREATE TABLE att (att_id NUMBER, incidentid NUMBER, attname VARCHAR2(20));
Table created.
SQL> INSERT INTO att VALUES (101, 1, 'attachment 1');
1 row created.
SQL> INSERT INTO att VALUES (102, 1, 'attachment 2');
1 row created.
SQL> INSERT INTO att VALUES (103, 1, 'attachment 3');
1 row created.
SQL> INSERT INTO att VALUES (104, 1, 'attachment 4');
1 row created.
SQL> INSERT INTO att VALUES (105, 1, 'attachment 5');
1 row created.
SQL> INSERT INTO att VALUES (110, 2, 'attachment A');
1 row created.
SQL> INSERT INTO att VALUES (111, 2, 'attachment B');
1 row created.
SQL> INSERT INTO att VALUES (112, 2, 'attachment C');
1 row created.
SQL> CREATE TABLE comments (comment_id NUMBER, incidentid NUMBER, commenttext VARCHAR2(20));
Table created.
SQL> INSERT INTO comments VALUES (201, 1, 'first comment');
1 row created.
SQL> INSERT INTO comments VALUES (202, 1, 'second comment');
1 row created.
SQL> INSERT INTO comments VALUES (203, 1, 'third comment');
1 row created.
建议查询:
SQL> WITH a AS (
2 SELECT att.incidentid
3 , COUNT(att.att_id) rows_per_incident
4 FROM att
5 GROUP BY att.incidentid
6 UNION ALL
7 SELECT comments.incidentid
8 , COUNT(comments.comment_id) rows_per_incident
9 FROM comments
10 GROUP BY comments.incidentid
11 )
12 , b AS (
13 SELECT inc.incidentid
14 , inc.incname
15 , ROW_NUMBER()
16 OVER (PARTITION BY inc.incidentid ORDER BY NULL) row_num
17 FROM inc
18 , (SELECT ROWNUM multiplier FROM DUAL CONNECT BY LEVEL <= (SELECT MAX(rows_per_incident) FROM a))
19 )
20 , c AS (
21 SELECT att.att_id
22 , att.incidentid
23 , att.attname
24 , ROW_NUMBER()
25 OVER (PARTITION BY att.incidentid ORDER BY att.att_id) att_rn
26 FROM att
27 )
28 , d AS (
29 SELECT comments.comment_id
30 , comments.incidentid
31 , comments.commenttext
32 , ROW_NUMBER()
33 OVER (PARTITION BY comments.incidentid ORDER BY comments.comment_id) comm_rn
34 FROM comments
35 )
36 , e AS (
37 SELECT c.incidentid
38 , c.att_id
39 , c.attname
40 , c.att_rn rn
41 , d.comment_id
42 , d.commenttext
43 FROM c
44 , d
45 WHERE c.incidentid = d.incidentid (+)
46 AND c.att_rn = d.comm_rn (+)
47 UNION ALL
48 SELECT TO_NUMBER(NULL) incidentid
49 , TO_NUMBER(NULL) att_id
50 , NULL attname
51 , d.comm_rn rn
52 , d.comment_id
53 , d.commenttext
54 FROM d
55 WHERE NOT EXISTS (SELECT NULL
56 FROM c
57 WHERE c.incidentid = d.incidentid
58 AND c.att_rn = d.comm_rn)
59 )
60 , f AS (
61 SELECT b.incidentid
62 , b.incname
63 , b.row_num
64 , e.att_id
65 , e.attname
66 , e.comment_id
67 , e.commenttext
68 FROM b
69 LEFT OUTER JOIN e ON b.incidentid = e.incidentid
70 AND b.row_num = e.rn
71 )
72 SELECT f.incidentid
73 , f.incname
74 , f.att_id
75 , f.attname
76 , f.comment_id
77 , f.commenttext
78 FROM f
79 WHERE NOT (f.att_id IS NULL AND f.comment_id IS NULL)
80 ORDER BY f.incidentid
81 , f.row_num
82 ;
INCIDENTID INCNAME ATT_ID ATTNAME COMMENT_ID COMMENTTEXT
---------- -------------------- ---------- -------------------- ---------- --------------------
1 incident 1 101 attachment 1 201 first comment
1 incident 1 102 attachment 2 202 second comment
1 incident 1 103 attachment 3 203 third comment
1 incident 1 104 attachment 4
1 incident 1 105 attachment 5
2 incident 2 110 attachment A
2 incident 2 111 attachment B
2 incident 2 112 attachment C
8 rows selected.
SQL>