Oracle Database 12c企业版12.1.0.2.0版
我希望我只是遗漏了一些东西,但是如果我在没有“connect by”的情况下运行这个查询,我会得到2行。当我添加“按级别连接< = 4”时,我希望将这2行中的每一行都添加4次。实际结果不同。
任何人都可以帮我理解这里发生的事情吗?我不是在寻找一个只能重复每行4次的解决方案 - 我已经知道了。我只是想了解发生了什么以及为什么。
ID BETA_NO THE_LEVEL
1 1 1 1 1 2 1 1 2 1 1 3 1 1 3 1 1 3 1 1 3 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4 1 1 4 1 2 1 1 2 2 1 2 2 1 2 3 1 2 3 1 2 3 1 2 3 1 2 4 1 2 4 1 2 4 1 2 4 1 2 4 1 2 4 1 2 4 1 2 4
1 with t as (select 1 as id from dual union all 2 select 2 from dual) 3 -- 4 select id, level 5 ,prior id 6 ,sys_connect_by_path(id,'=>') as cpath 7 from t 8* connect by level <= 3 SQL> / ID LEVEL PRIORID CPATH ---------- ---------- ---------- -------------------------------------------------- 1 1 =>1 1 2 1 =>1=>1 1 3 1 =>1=>1=>1 2 3 1 =>1=>1=>2 2 2 1 =>1=>2 1 3 2 =>1=>2=>1 2 3 2 =>1=>2=>2 2 1 =>2 1 2 2 =>2=>1 1 3 1 =>2=>1=>1 2 3 1 =>2=>1=>2 2 2 2 =>2=>2 1 3 2 =>2=>2=>1 2 3 2 =>2=>2=>2 14 rows selected.
选择了30行
非常感谢mathguy。他在下面的答案中提供的第二个链接正是我正在寻找的。具体做法是:
public final class ConfigCache {
private static final MultiKeyMap configCache = new MultiKeyMap();
@Autowired
private ConfigDao dao;
@PostConstruct
public void init() {
Map<String, Collection<Configuration>> map = null;
try {
if (configurationCache != null || configurationCache.isEmpty()) {
map = dao.loadConfigurations();
map.forEach((k, v) -> {
v.forEach((c) -> {
configCache.put(k, c.getAttributeName(), c.getAttributeValue());
});
});
}
} catch (DaoException e) {
throw new RuntimeException(e);
}
}
public Object getValue(String k1, String k2) {
return configurationCache.get(k1, k2);
}
@PreDestroy
public void clearCache() {
if (configCache != null) {
configCache.clear();
}
}
}
我从这个例子中可以清楚地看到,但我很难简洁地说出来。
答案 0 :(得分:2)
除了&#34; level&lt; = 4&#34;之外的任何条件,原始表,视图等中的每一行(在这种情况下来自连接)将在2级产生两行,然后是4 3级更多行,4级更多8行。&#34; Connect by&#34;本质上是一系列连接,如果PRIOR运算符没有条件,则表示正在进行交叉连接。
您可能想要添加&#34;并且先前a.id = a.id&#34;。这将导致Oracle抱怨周期(因为Oracle在看到PRIOR列中的相同值时决定达到一个周期)。反过来,这通过添加第三个条件来解决,通常是&#34;并且先前的sys_guid()不是空的&#34;。
(已编辑;原始答案引用了NOCYCLE,使用&#34时不需要;之前的sys_guid()不是null&#34;方法。)
最近在OTN上讨论过这个问题:https://community.oracle.com/thread/3999985
这里讨论了同样的问题:https://community.oracle.com/thread/2526535
答案 1 :(得分:0)
为了说明Mathguy的答案,你缺少CONNECT BY子句中的一些谓词:
with alpha as (
select 1 as id
from dual
),
beta as (
select 1 as alpha_id,
1 as beta_no
from dual
union all
select 1 as alpha_id,
2 as beta_no
from dual
)
select a.id,
b.beta_no,
level as the_level
from alpha a
inner join beta b
on b.alpha_id = a.id
connect by level <= 4
AND PRIOR a.id = a.id
AND PRIOR b.beta_no = b.beta_no
AND PRIOR sys_guid() IS NOT NULL
order by a.id,
b.beta_no,
LEVEL;
ID BETA_NO THE_LEVEL
---------- ---------- ----------
1 1 1
1 1 2
1 1 3
1 1 4
1 2 1
1 2 2
1 2 3
1 2 4
另一种方法是使用recursive with子句:
with alpha as (
select 1 as id
from dual
),
beta as (
select 1 as alpha_id,
1 as beta_no
from dual
union all
select 1 as alpha_id,
2 as beta_no
from dual
),
multiply (id, beta_no, rn) AS (SELECT a.id,
b.beta_no,
1 rn
FROM alpha a
INNER JOIN beta b
ON a.id = b.alpha_id
UNION ALL
SELECT ID,
beta_no,
rn + 1
FROM multiply
WHERE rn + 1 <= 4)
SELECT ID,
beta_no,
rn AS the_level
FROM multiply
order by id,
beta_no,
rn;
ID BETA_NO THE_LEVEL
---------- ---------- ----------
1 1 1
1 1 2
1 1 3
1 1 4
1 2 1
1 2 2
1 2 3
1 2 4