示例
ID NAME QTY
1 A 3
1 B 2
2 A 0
2 A 1如何通过一条SQL得出以下结果呢?
ID NAME QTY ROWNUM
1 A 3 1
1 A 3 2
1 A 3 3
1 B 2 1
1 B 2 2
2 A 1 1即根据QTY产生重复记录,产生的记录数 = QTY值,如果为0不产生记录,QTY数值大小不固定.
ID NAME QTY
1 A 3
1 B 2
2 A 0
2 A 1如何通过一条SQL得出以下结果呢?
ID NAME QTY ROWNUM
1 A 3 1
1 A 3 2
1 A 3 3
1 B 2 1
1 B 2 2
2 A 1 1即根据QTY产生重复记录,产生的记录数 = QTY值,如果为0不产生记录,QTY数值大小不固定.
(select 1 ID, 'A' NAME, 3 QTY from dual
union
select 1 ID, 'B' NAME, 2 QTY from dual
union
select 2 ID, 'A' NAME, 0 QTY from dual
union
select 2 ID, 'A' NAME, 1 QTY from dual
) select t.*,row_number() over(partition by QTY order by id)
from (
select * from a where QTY !=0
) t
connect by rownum<=QTY
from (
select * from a where QTY >0
) t
connect by rownum <=QTY
SELECT ID, NAME,QTY,RN FROM TEST,
(SELECT ROWNUM RN FROM DUAL CONNECT BY ROWNUM<=(SELECT MAX(QTY) FROM TEST)) A
WHERE TEST.QTY<=A.RN这条SQL出来的结果是没有问题,但是当TEST表记录数较多,QTY大一点时,,会很慢很慢
ID NAME QTY RN
---------- ---- ---------- ----------
2 A 0 1
2 A 1 1
1 B 2 2
2 A 0 2
2 A 1 2
1 A 3 3
1 B 2 3
2 A 0 3
2 A 1 3你的sql语句出来的是这个结果,应该不是你想要的吧
SQL> SELECT * FROM TEST_DD; ID NAME QTY
---------- ---- ----------
1 A 3
1 B 2
2 A 0
2 A 1SQL> SELECT TT.*, LEVEL
2 FROM TEST_DD TT
3 START WITH QTY <> 0
4 CONNECT BY PRIOR QTY = QTY - 1
5 ORDER BY 1, 2, 3, 4; ID NAME QTY LEVEL
---------- ---- ---------- ----------
1 A 3 1
1 A 3 2
1 A 3 3
1 B 2 1
1 B 2 2
2 A 1 16 rows selectedSQL> SELECT *
2 FROM TEST_DD T1,
3 (SELECT ROWNUM RN
4 FROM DUAL
5 CONNECT BY ROWNUM < (SELECT SUM(QTY) SUM_QTY FROM TEST_DD)) T2
6 WHERE QTY >= RN
7 ORDER BY 1, 2, 3, 4; ID NAME QTY RN
---------- ---- ---------- ----------
1 A 3 1
1 A 3 2
1 A 3 3
1 B 2 1
1 B 2 2
2 A 1 16 rows selected
(select 1 ID, 'A' NAME, 3 QTY from dual
union
select 2 ID, 'B' NAME, 2 QTY from dual
union
select 3 ID, 'A' NAME, 1 QTY from dual
union
select 4 ID, 'c' NAME, 0 QTY from dual
)
select ID, NAME, QTY, row_number() over(partition by QTY order by QTY) rw
from (select a.*, rownum r1
from (select a.*,
sum(QTY) over(order by QTY desc rows between unbounded preceding and current row) - QTY r
from test a
order by QTY desc) a
connect by rownum - r <= qty)
where r1 - qty <= r
示例
ID NAME QTY
1 A 3
1 B 2
2 A 0
2 A 1
根据这个表编写个存储过程, 游标查询所有数据, 如果QTY为0,pass, 如果>0, insert into aaaa(临时表) QTY-1.select * from aaaa; //这条SQL就能查出你需要的数据。
我执行怎么不行呢,报“用户数据中的 connect by 循环”错误,难道是我的数据库版本有问题(oracle 9i)?
SQL> SELECT *
2 FROM TEST_DD T1,
3 (SELECT ROWNUM RN
4 FROM ALL_OBJECTS
5 WHERE ROWNUM <= (SELECT SUM(QTY) SUM_QTY FROM TEST_DD)) T2
6 WHERE QTY >= RN
7 ORDER BY 1, 2, 3, 4; ID NAME QTY RN
---------- ---- ---------- ----------
1 A 3 1
1 A 3 2
1 A 3 3
1 B 2 1
1 B 2 2
2 A 1 16 rows selected
但万一 qty > all_objects 的记录总数,就有问题了。
因为你的9i的数据库在运用CONNECT BY方面会有限制,10G以上版本的数据库就已经把CONNECT BY“做”得非常完善了。
如果本人上面写的3种方法在9i下都不行,那就只能考虑存储过程的方式了。
GOOD LUCK!~
SQL> with t as
2 (select 1 ID, 'A' NAME, 3 QTY from dual
3 union
4 select 1 ID, 'B' NAME, 2 QTY from dual
5 union
6 select 2 ID, 'A' NAME, 0 QTY from dual
7 union
8 select 2 ID, 'A' NAME, 1 QTY from dual
9 )
10 select *
11 from t t1, (select level l from dual connect by level <= (select max(QTY) from t)) t2
12 where t1.qty >= t2.l
13 order by t1.id, t1.name, t2.l; ID N QTY L
---------- - ---------- ----------
1 A 3 1
1 A 3 2
1 A 3 3
1 B 2 1
1 B 2 2
2 A 1 1
经常见到一个问题不是用语言硬解就是用sql硬解,还是两者结合比较好吧
SELECT a.*, LEVEL
FROM tablename a
START WITH QTY <> 0
CONNECT BY PRIOR QTY = QTY - 1
ORDER BY id
create table t2(id int,name varchar2(10),qty int)
insert into t2
select 1,'A',3 from dual
union all
select 1,'B',2 from dual
union all
select 2,'A',0 from dual
union all
select 2,'A',1 from dual
create table temp(id int)
insert into temp
select 1 from dual
union all
select 2 from dual
union all
select 3 from dual
union all
select 4 from dual
union all
select 5 from dual
union all
select 6 from dualselect * from
(select distinct * from t2) a,temp b
where a.qty-b.id>=0
order by a.id,a.name,a.qty,b.id
create table t2(id int,name varchar2(10),qty int)
insert into t2
select 1,'A',3 from dual
union all
select 1,'B',2 from dual
union all
select 2,'A',0 from dual
union all
select 2,'A',1 from dual
select id,name,qty,level from t2 a
start with qty<>0
connect by prior qty=qty-1
order by a.id,a.name,a.qty
SELECT * FROM
(SELECT ID,NAME,QTY,ROW_NUMBER() OVER(PARTITION BY ID,NAME ORDER BY ID) RN FROM
(SELECT T.* FROM T,DBA_OBJECTS WHERE QTY!=0))
WHERE RN<=QTY结果:
ID NAME QTY RN
1 A 3 1
1 A 3 2
1 A 3 3
1 B 2 1
1 B 2 2
2 A 1 1