我的要求是查找一个月中所有经过的日子。以下是我的示例查询。
CREATE TABLE custom.date_full (
sno NUMBER,
curr_date DATE);
INSERT INTO custom.date_full VALUES ( 1,'27-sep-2018' );
INSERT INTO custom.date_full VALUES ( 2,'27-sep-2018' );
--Query:1 - RETURNS 4 RECORDS AS EXPECTED
SELECT curr_date,
TRUNC (curr_date, 'MM') + LEVEL - 1 AS DAY,
LEVEL
FROM (SELECT * FROM custom.date_full WHERE sno=1)
CONNECT BY level<=4
ORDER BY DAY;
--Query 2: RETURNS 15 RECORDS WITH DUPLICATES
SELECT curr_date,
TRUNC (curr_date, 'MM') + LEVEL - 1 AS DAY,
LEVEL
FROM custom.date_full
WHERE sno=1
CONNECT BY level<=4
ORDER BY DAY;
我的Query 1
工作正常,但是Query 2
显示重复的记录。为什么?
答案 0 :(得分:5)
您不了解CONNECT BY
的工作方式。这是Oracle如何评估第二查询的演练。
没有START WITH
子句,表中的每一行都将用作起点或层次结构中的“根”。
由于您没有CONNECT BY
条件(例如“ columnA = PRIOR columnB”),因此表中的每一行将被视为每隔一行的子级。这将永远发生,直到达到您的LEVEL <=4
条件为止。
所以
LEVEL 1
--------
SNO 1
SNO 2
说明:表中的每一行都是其自身层次结构的起点(因为您没有START WITH
条件)。
LEVEL 2
--------
SNO 1 -> SNO 1
SNO 1 -> SNO 2
SNO 2 -> SNO 1
SNO 2 -> SNO 2
这4行的说明-SNO 1和SNO 2都是根,而对于每个根,SNO 1和SNO 2都是子代。因此,2x2行= 4行。
LEVEL 3
-------
SNO 1 -> SNO 1 -> SNO 1
SNO 1 -> SNO 1 -> SNO 2
SNO 1 -> SNO 2 -> SNO 1
SNO 1 -> SNO 2 -> SNO 2
SNO 2 -> SNO 1 -> SNO 1
SNO 2 -> SNO 1 -> SNO 2
SNO 2 -> SNO 2 -> SNO 1
SNO 2 -> SNO 2 -> SNO 2
这8行的说明。从级别2的4行开始,SNO 1和SNO 2均为子级,在级别3给出4x2 = 8行。
我不会画的第4级,同样会给出8x2 = 16行。
因此,总共有2 + 4 + 8 + 16 = 30行。 (即1级+ 2级+ 3级+ 4级)。
然后,在CONNECT BY
处理(如上所示)之后 ,将应用WHERE
子句,将最终结果限制为该值(在层次结构)为SNO = 1
。这正好是您得到的30行或15行的一半。
答案 1 :(得分:0)
使用CONNECT BY
创建一个层次查询。通常,它还包括START WITH
,用于指定作为层次结构查询的父级/根级的行。如果没有START WITH
,则表中的所有行均用作父/根行。
在Query 1
中,父级/根级是具有1行的表:
FROM (SELECT * FROM custom.date_full WHERE sno=1)
在Query 2
中,父级/根级是具有2行的表:
FROM custom.date_full
这种START WITH
和CONNECT BY
关系确定层次结构中的行将如何连接到结果中。
Query
中没有重复项,因为只有一个父行与多个子行有关系。
Query 2
中有重复的结果,因为有多个父行与多个子行有关系。
以下资源中提供了更多常规信息: