为什么我的层次结构查询显示重复记录?

时间:2018-10-23 13:31:49

标签: sql oracle

我的要求是查找一个月中所有经过的日子。以下是我的示例查询。

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显示重复的记录。为什么?

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都是根,而对于每个根,SN​​O 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 WITHCONNECT BY关系确定层次结构中的行将如何连接到结果中。

Query中没有重复项,因为只有一个父行与多个子行有关系。

Query 2中有重复的结果,因为有多个父行与多个子行有关系。


以下资源中提供了更多常规信息: