我的要求是找到一个月内所有失效的天数.以下是我的示例查询.
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;
Run Code Online (Sandbox Code Playgroud)
我的Query 1作品很好,但Query 2显示重复的记录.为什么?
你不明白是如何CONNECT BY运作的.以下是Oracle如何评估您的第二个查询的演练.
如果没有START WITH子句,表中的每一行都将用作层次结构中的起点或"根".
由于您没有CONNECT BY条件(例如"columnA = PRIOR columnB"),因此表中的每一行都将被视为每隔一行的子项.这将永远发生,直到LEVEL <=4达到你的状况.
所以,
LEVEL 1
--------
SNO 1
SNO 2
Run Code Online (Sandbox Code Playgroud)
说明:表中的每一行都是其自己的层次结构的起点(因为没有START WITH条件).
LEVEL 2
--------
SNO 1 -> SNO 1
SNO 1 -> SNO 2
SNO 2 -> SNO 1
SNO 2 -> SNO 2
Run Code Online (Sandbox Code Playgroud)
这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
Run Code Online (Sandbox Code Playgroud)
这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行中的一半,这就是你得到的.