表tab1中有如下两条记录,
字段A 字段B
记录1:0121(大类) 60.00
记录2:0121001(小类) 70.00 表tab2中,有一字段c,有可能是4位,有可能是6位,与tab1中的A字段是相等的,现在的要求是先要满足6位的,如果6位的记录没有,就找4位的。也就是说,如果 where tab2.c=tab1.A 没有找到匹配的记录,就用where substr(tab2.c,0,4)=tab1.A 也就是先找小类,如果小类不满足,就继续找大类,要求这个条件写在一个SQL语句里。
也就是像这样的:
where (tab2.c=tab1.A or substr(tab2.c,1,4)=tab1.A
但是,上面这样会把两条记录都查出来,我要的结果是如果tab2.c=tab1.A满足的话,就取出70.00,不再执行substr(tab2.c,1,4)=tab1.A了。 谢谢
字段A 字段B
记录1:0121(大类) 60.00
记录2:0121001(小类) 70.00 表tab2中,有一字段c,有可能是4位,有可能是6位,与tab1中的A字段是相等的,现在的要求是先要满足6位的,如果6位的记录没有,就找4位的。也就是说,如果 where tab2.c=tab1.A 没有找到匹配的记录,就用where substr(tab2.c,0,4)=tab1.A 也就是先找小类,如果小类不满足,就继续找大类,要求这个条件写在一个SQL语句里。
也就是像这样的:
where (tab2.c=tab1.A or substr(tab2.c,1,4)=tab1.A
但是,上面这样会把两条记录都查出来,我要的结果是如果tab2.c=tab1.A满足的话,就取出70.00,不再执行substr(tab2.c,1,4)=tab1.A了。 谢谢
SQL> SELECT * FROM TABLE1;A B
-------------------- ----------
0121 60.00
012101 70.00
0122 110.00
012301 230.00
012303 45.00
0123 80.006 rows selectedSQL> SELECT * FROM TABLE2;C
--------------------
012101
0122
0123SQL> SELECT A, B
2 FROM (SELECT T1.*,
3 ROW_NUMBER() OVER(PARTITION BY SUBSTR(T1.A, 0, 4) ORDER BY T1.A DESC) RN
4 FROM TABLE1 T1) TT
5 WHERE EXISTS (SELECT 1
6 FROM TABLE2 T2
7 WHERE DECODE(T2.C, TT.A, T2.C, SUBSTR(TT.A, 0, 4)) =
8 DECODE(T2.C, TT.A, T2.C, SUBSTR(T2.C, 0, 4)))
9 AND RN = 1;A B
-------------------- ----------
012101 70.00
0122 110.00
012303 45.00
序号 字段A 字段B
1 0121 60.00
2 0121001 70.00现在表2里有一字段C,该字段同表1的A字段样,有可能是4位,有可能是6位,现在两表结合查询,条件是要首先满足小类,再满足大类(0121是大类,0121001是小类)假设:现在表2里的字段C=0121001如果现在表1中只有第二条记录,现在表2中的字段C=0121001,表1的第二条记录刚好匹配,应取出70.00
如果现在表1中只有第一条记录,那就是substr(表2.C,1,4)=表1.A),就应取出60.00
问题是:如果表1中这两条记录同时存在,如何先满足小类,再满足大类?(如果两条记录同时存在,应得到70.00)我看了一下楼上的好像都有道理,但还没验证~~~
where length(a)=(select max(length(m.a))
from tab1 m,tab2 n
where 1 = decode(m.a,
n.c,
1,
substr(n.c,1,4),
1,
0
)
)
;
因为我那是两个表结合查询,如果不加上面的这个判断条件,两表结合后的结果集如下:
序号 字段1 字段2
1 0121 60.00
2 0121001 70.00用了1楼和2楼的方法,查询结果是一样的。
因为表2中的字段C=‘0121001’,无论是decode还是case,都是在其自身行中进行判断,当游标走到第一条记录时,会用到查询中的substr,走到第二条记录时,是直接相等。所以两条记录同时查出来了。现在表2.C=‘0121001’,应该取出70我的实际程序中是4个表关联查询,是一个循环(放在for rec里面的),每个表的主键多达5个以上,而且还有其它条件的判断也较复杂。4楼的用到了排序,虽然结果是预期输出的,但使得整个程序变得非常庞杂,都理不清了。实在没有办法了,今天我把4个表拆开了,选了两个表作基表放在最外层的循环里,另两个表放在循环内部,这样问题倒是解决了,但整个程序看起来似乎重复的代码较多(因为代码本来就较长,那两个表的判断我先是用的"=",如果no_data_found,就用"substr")。6楼的我明天再试一下。感谢楼上各位的相助,如果还有其它方法,也请提出来,我再去试一下,力求找到一个最好的解决方案,谢谢各位啦~~~
scott@ORA1> select * from tab1;A F2
-------------------- --------------------
0121 60
0121001 70scott@ORA1> select * from tab2;C
--------------------
0121001scott@ORA1> SELECT *
2 FROM (
3 select tab1.*
4 ,tab2.*
5 ,row_number() over(partition by tab2.C order by length(tab1.A) DESC) rn
6 from tab1, tab2
7 where tab1.A = tab2.C
8 or tab1.A = substr(tab2.c,1,4)
9 )
10 WHERE rn = 1;A F2 C RN
-------------------- -------------------- -------------------- ----------
0121001 70 0121001 1
where exists
(
select * from tab2 b
where a.A=b.C or substr(b.C,1,4)=a.A
)
group by substr(A,1,4)
---------- ----------
0121 60.00
012101 90.00
0123 65.00
0125 70.00
012504 68.00SQL> select a, b
2 from (select a,
3 b,
4 row_number() over(partition by substr(a, 1, 4) order by a desc) rn
5 from test)
6 where rn = 1;A B
---------- ----------
012101 90.00
0123 65.00
012504 68.00
SQL> select * from tab;A B
-------- ----------
0121 60.00
012101 70.00
0122 110.00
0124 230.00
012303 45.00
0123 80.006 rows selectedSQL> select * from tab2;C
------
012101
0122
012302
0121SQL> select t.f1, t.f2
2 from (select m.a f1,
3 m.b f2,
4 n.c f3,
5 row_number() over(partition by m.a order by length(n.c) desc) f4
6 from tab m, tab2 n
7 where 1 = decode(m.a, n.c, 1, substr(n.c, 1, 4), 1, 0)) t
8 where t.f4 = 1;F1 F2
-------- ----------
0121 60.00
012101 70.00
0122 110.00
0123 80.00SQL>