一道SQL题

sweat89 2012-03-31 07:46:58


A表
type_id name parent_id
1 a 0
2 b 0
3 c 0
4 b1 2
5 b2 2




B表
id name type_id
1 tt 4
2 yy 5



求type_id 为2 的所有子元素(也就是找tt,yy), 在线等······
...全文
146 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复

SELECT * FROM tb_A
CONNECT BYPRIOR type_id = parent_id
START WITH type_id = '2'

ssqtjffcu 2012-03-31
  • 打赏
  • 举报
回复

with a as(
select 1 type_id,'a' name,0 parent_id from dual
union all
select 2,'b',0 from dual
union all
select 3,'c',0 from dual
union all
select 4,'b1',2 from dual
union all
select 5,'b2',2 from dual
),b as(
select 1 id,'tt' name,4 type_id from dual
union all
select 2,'yy',5 from dual
)select type_id from b
where exists
(select 1 from
(select type_id from a where
type_id<>2 connect by prior type_id=parent_id start with type_id=2) c
where c.type_id=b.type_id)

TYPE_ID
----------
4
5
「已注销」 2012-03-31
  • 打赏
  • 举报
回复
select B.name,B.type_id,A.parent_id from A left outer join B on
(A.type_id = b.type_id) where A.parent_id = 2;
不知道你是 只是查询 还是要写递归
dawugui 2012-03-31
  • 打赏
  • 举报
回复
/*********************************************************************************************
http://www.itpub.net/620932.html
问题提出:
一个高级SQL语句问题
假设有一张表,A和B字段都是NUMBER,
A B
1 2
2 3
3 4
4
有这样一些数据
现在想用一条SQL语句,查询出这样的数据
1-》2-》3—》4
就是说,A和B的数据表示一种连接的关系,现在想通过A的一个值,去查询A所对应的B值,直到B为NULL为止,
不知道这个SQL语句怎么写?请教高手!谢谢

*********************************************************************************************/

--以下是利用分析函数的一个简单解答:
--start with connect by可以参考http://www.itpub.net/620427.html

CREATE TABLE TEST(COL1 NUMBER(18,0),COL2 NUMBER(18,0));

INSERT INTO TEST VALUES(1,2);
INSERT INTO TEST VALUES(2,3);
INSERT INTO TEST VALUES(3,4);
INSERT INTO TEST VALUES(4,NULL);

INSERT INTO TEST VALUES(5,6);
INSERT INTO TEST VALUES(6,7);
INSERT INTO TEST VALUES(7,8);
INSERT INTO TEST VALUES(8,NULL);

INSERT INTO TEST VALUES(9,10);
INSERT INTO TEST VALUES(10,NULL);

INSERT INTO TEST VALUES(11,12);
INSERT INTO TEST VALUES(12,13);
INSERT INTO TEST VALUES(13,14);
INSERT INTO TEST VALUES(14,NULL);


CREATE TABLE TEST(COL1 NUMBER(18,0),COL2 NUMBER(18,0));

INSERT INTO TEST VALUES(1,2);
INSERT INTO TEST VALUES(2,3);
INSERT INTO TEST VALUES(3,4);
INSERT INTO TEST VALUES(4,NULL);

INSERT INTO TEST VALUES(5,6);
INSERT INTO TEST VALUES(6,7);
INSERT INTO TEST VALUES(7,8);
INSERT INTO TEST VALUES(8,NULL);

INSERT INTO TEST VALUES(9,10);
INSERT INTO TEST VALUES(10,NULL);

select max(col) from(
select SUBSTR(col,1,CASE WHEN INSTR(col,'->')>0 THEN INSTR(col,'->') - 1 ELSE LENGTH(col) END) FLAG,col from(
select ltrim(sys_connect_by_path(col1,'->'),'->') col from (
select col1,col2,CASE WHEN LAG(COL2,1,NULL) OVER(ORDER BY ROWNUM) IS NULL THEN 1 ELSE 0 END FLAG
from test
)
start with flag=1 connect by col1=prior col2
)
)
group by flag
;


Oracle中connect by...start with...的使用

一、语法
大致写法:select * from some_table [where 条件1] connect by [条件2] start with [条件3];
其中 connect by 与 start with 语句摆放的先后顺序不影响查询的结果,[where 条件1]可以不需要。
[where 条件1]、[条件2]、[条件3]各自作用的范围都不相同:

[where 条件1]是在根据“connect by [条件2] start with [条件3]”选择出来的记录中进行过滤,是针对单条记录的过滤, 不会考虑树的结构;

[条件2]指定构造树的条件,以及对树分支的过滤条件,在这里执行的过滤会把符合条件的记录及其下的所有子节点都过滤掉;

[条件3]限定作为搜索起始点的条件,如果是自上而下的搜索则是限定作为根节点的条件,如果是自下而上的搜索则是限定作为叶子节点的条件;

示例:
假如有如下结构的表:some_table(id,p_id,name),其中p_id保存父记录的id。
select * from some_table t where t.id!=123 connect by prior t.p_id=t.id and t.p_id!=321 start with t.p_id=33 or t.p_id=66;

对prior的说明:
prior存在于[条件2]中,可以不要,不要的时候只能查找到符合“start with [条件3]”的记录,不会在寻找这些记录的子节点。要的时候有两种写法:connect by prior t.p_id=t.id 或 connect by t.p_id=prior t.id,前一种写法表示采用自上而下的搜索方式(先找父节点然后找子节点),后一种写法表示采用自下而上的搜索方式(先找叶子节点然后找父节点)。

二、执行原理
connect by...start with...的执行原理可以用以下一段程序的执行以及对存储过程RECURSE()的调用来说明:

/* 遍历表中的每条记录,对比是否满足start with后的条件,如果不满足则继续下一条,
如果满足则以该记录为根节点,然后调用RECURSE()递归寻找该节点下的子节点,
如此循环直到遍历完整个表的所有记录 。*/
for rec in (select * from some_table) loop
if FULLFILLS_START_WITH_CONDITION(rec) then
RECURSE(rec, rec.child);
end if;
end loop;

/* 寻找子节点的存储过程*/
procedure RECURSE (rec in MATCHES_SELECT_STMT, new_parent IN field_type) is
begin
APPEND_RESULT_LIST(rec); /*把记录加入结果集合中*/
/*再次遍历表中的所有记录,对比是否满足connect by后的条件,如果不满足则继续下一条,
如果满足则再以该记录为根节点,然后调用RECURSE()继续递归寻找该节点下的子节点,
如此循环直到找至叶子节点。*/
for rec_recurse in (select * from some_table) loop
if FULLFILLS_CONNECT_BY_CONDITION(rec_recurse.child, new_parent) then
RECURSE(rec_recurse,rec_recurse.child);
end if;
end loop;
end procedure RECURSE;

三、使用探讨
从上面的执行原理可以看到“connect by...start with...”构造树的方式是:(1)如果是自上而下方式,则把表中的每一条记录都作为根节点来生成树,所以表中有多少条记录就会构造出多少棵树。(2)如果是自下而上的搜索方式,则把表中的每一条记录都作为叶子节点来生成分支,所以表中有多少条记录就会生成多少条分支。
因此如果表中的记录不是严格遵照每条记录都只能有一个父记录的原则,那么就可能有部分记录会存在于多棵树中,那么在查找记录的时候就可能会出现找到多条重复记录的异常情况。

dawugui 2012-03-31
  • 打赏
  • 举报
回复
这个需要使用connect by ,提供相关示例,自己参照着修改:
--1.Hierarchical Queries: START WITH and CONNECT BY PRIOR clauses 
--Hierarchical Queries
--START WITH and CONNECT BY PRIOR clauses.

SELECT employee_id, manager_id, first_name, last_name
FROM employee_jh
START WITH employee_id = 1
CONNECT BY PRIOR employee_id = manager_id;

EMPLOYEE_ID MANAGER_ID FIRST_NAME LAST_NAME
----------- ---------- ---------- ----------
1 0 James Smith
2 1 Ron Johnson
3 2 Fred Hobbs
5 2 Rob Green
4 1 Susan Jones
6 4 Jane Brown
9 6 Henry Heyson
7 4 John Grey
8 7 Jean Blue
10 1 Kevin Black
11 10 Keith Long
12 10 Frank Howard
13 10 Doreen Penn

13 rows selected.

--2.Using a Subquery in a START WITH Clause
SELECT LEVEL,
LPAD(' ', 2 * LEVEL - 1) || first_name || ' ' || last_name AS employee
FROM employee_jh
START WITH employee_id = (SELECT employee_id FROM employee_jh WHERE first_name = 'Kevin' AND last_name = 'Black')
CONNECT BY PRIOR employee_id = manager_id;

LEVEL EMPLOYEE
---------- -------------------------
1 Kevin Black
2 Keith Long
2 Frank Howard
2 Doreen Penn

--3.Including Other Conditions in a Hierarchical Query
SELECT LEVEL,
LPAD(' ', 2 * LEVEL - 1) || first_name || ' ' ||
last_name AS employee, salary
FROM employee_jh
WHERE salary <= 50000
START WITH employee_id = 1
CONNECT BY PRIOR employee_id = manager_id;

LEVEL EMPLOYEE SALARY
---------- ------------------------- ----------
3 Rob Green 40000
3 Jane Brown 45000
4 Henry Heyson 30000
3 John Grey 30000
4 Jean Blue 29000
3 Keith Long 50000
3 Frank Howard 45000
3 Doreen Penn 47000

8 rows selected.

17,377

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 基础和管理
社区管理员
  • 基础和管理社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧