2 qq 25393765 qq_25393765 于 2017.09.07 15:51 提问

oracle使用游标怎么比较上下行的数据 50C

假设我经过如干个子查询按照 ORDER BY A_NAME,B_NAME后,得到以下的数据

A_name B_name C_name
A1 A1_B1 60
A1 A1_B2 80
A1 A1_B3 100
A1 A1_B4 120

A2 A2_B1 70
A2 A2_B2 90
A2 A2_B3 50
A2 A2_B4 100

A3 A3_B1 90
A3 A3_B2 80
A3 A3_B3 100
A3 A3_B4 120

我想比较C_name这列中在同一个 A_name中按照 B_name排序排序的 C_name是不是依次增大的,如果不是就把这组数据找出来,或者做标记,比如上面的数据,最终我需要得到 A2,A3这两组数据,或者在给这两组数据做个标记。

我的思路是写一个函数来比较C_name,但是不知道怎么实现,可以在函数中使用游标,各位大神有什么建议吗?十万火急的.
这最终是做成一个报表数据中错误核查的,同一个A_name中 按照 B_name 排序,C_name应该一次增大,否则就是错误数据,现在就是把错误数据找出来

6个回答

dcxy0
dcxy0   Ds   Rxr 2017.09.07 16:19

没有用游标实现过类似需求,如果数据不多的话,可以取到Java里面处理,在Java里面有Stream流可以用来出来排序.

参考资料:

https://www.ibm.com/developerworks/cn/java/j-java-streams-1-brian-goetz/index.html

dcxy0
dcxy0 回复正在进化的程序员: ...这就有点爱莫能助了。。。。。。
3 个月之前 回复
qq_25393765
qq_25393765 如果可以用Java处理的话我就不会提问了,就是必须用SQL处理
3 个月之前 回复
lkhog
lkhog   2017.09.07 16:36

游标里先按aname分组 分数排序 ;之后利用每个相同组里的分数顺序 再从按aname bname 分组之后的子集中 通过分数判断是否存在记录 如果出现一条不满足 则标记 。测试时候 排序是关键

qq_25393765
qq_25393765 我是传入A_name的名字,然后按照B_name排序,然后就是检查C_name的数值是不是依次增大的,就是想这这样的一个函数,有什么建议吗。或者可不可以写出SQL语句来,(难过中)
3 个月之前 回复
lkhog
lkhog   2017.09.07 16:44

外层游标先按aname、bname、cname排序 内层游标安 aname、cname、bname、排序 判断bname是否相等

qq_25393765
qq_25393765 大神,大神,还在吗
3 个月之前 回复
qq_25393765
qq_25393765 回复lkhog: 好的,万分感谢大神!我是刚开始工作的小程序,遇到这个问题困扰了我两天了,大神可以交个朋友吗
3 个月之前 回复
qq_25393765
qq_25393765 下面是我之前打算用游标实现的,按照你提供的思路好像不用游标也可以实现,这个我之前也有想想过这样写,不过具体还是不知道怎么写
3 个月之前 回复
lkhog
lkhog 晚上回去帮你写~在上班~
3 个月之前 回复
qq_25393765
qq_25393765 然后方便帮写一下吗。这是我之前打算用游标写的
3 个月之前 回复
qq_25393765
qq_25393765 这个思路也很有用,就是如果C_name的数值相同呢
3 个月之前 回复
qq_25393765
qq_25393765   2017.09.07 16:47

create or replace function compare_azimuth
(endoeb_CUID varchar2(225))
return boolean
is
tmp_radio VARCHAR2(255) --机电名
tmp_azimuth number(22) --数值
--查询同一楼层的机电数值(按机电名称排序)
CURSOR FLOO_COR IS -- 定义游标
SELECT T0.dynamo AS jidian, --机电名
nvl(T0.numtoo, 0) as shuzhi --数值
FROM T0
LEFT JOIN EX EXT
ON T0.CUID = EXT.CUID
WHERE T0.RELATED_BASESITE_CUID = endoeb_CUID --函数传入的参数
order by jidian
/* **********************************************************/
begin
OPEN ZAIM_COR --打开游标
LOOP
FETCH ZAIM_COR --提取数据
INTO tmp_radio,tmp_azimuth

        exit when 


         end loop;

  close ZAIM_COR; --关闭游标    

end

sunbocong
sunbocong   2017.09.07 17:43

SELECT DISTINCT t1.* FROM ttet t1 left JOIN ttet t2
ON t1.a_name=t2.a_name WHERE (t1.b_name>t2.b_name AND t1.c_name<t2.c_name)
ORDER BY t1.a_name,t1.b_name

sunbocong
sunbocong 回复正在进化的程序员: 我这写法是假设a,b,c都在一张叫ttet的表上。你的数据库如果是oracle或者postgresql的话可以试试with生成一个ttet表,然后接上我的这个查询就可以了
3 个月之前 回复
qq_25393765
qq_25393765 仿照了你的写法,查不出数据
3 个月之前 回复
qq_25393765
qq_25393765 我正在研究你的SQL语句,不过我的数据是A在一个表中,B和C在另一个表中
3 个月之前 回复
qq_25393765
qq_25393765 没看懂,这是直接写在查询中还是自定义函数中还是自定义函数的游标中
3 个月之前 回复
u013248350
u013248350   2017.09.07 22:14

如果只是上下行比较的话。你多添加一个变量指向就行了。
比如游标vernier -> A_name B_name C_name;
定义 i,j
判断i是否为空,若为空,则i = vernier.A_name ,j = vernier.C_name;跳下一次循环
若不为空,则判断 i 是否等于vernier.A_name
若等于,则判断 j 是否小于 vernier.C_name。小于则j = vernier.C_name记录当前值。若不小于就是要提出的记录。
若i不等于vernier.A_name,则重新记录 i = vernier.A_name ,j = vernier.C_name;跳下一次循环。
这样直到结束。

Csdn user default icon
上传中...
上传图片
插入图片