今天遇到的sql去重和查询问题

今天遇到了一点sql语句的问题,在这里做一下笔记。

------------

今天上午在调试程序的时候突然web页面突然挂了,查看后台提示发现为“单行查询返回多个行”,典型的有地方在查唯一值的时候出错了,结果查看sql果然有查唯一值的地方,这里sql形如:

select a,b,(select c from table1 where ..) c from table2.. where..

查询c的时候出现了多值。因为是之前的sql并且一直都没有问题,经过查表分析数据,果然发现是本次需求的改动引起。当然,首先表的设计就不太合理,table2的主键为两个字段key1,key2,而与table1对应的居然只有key1,而在根据需求改动的时候出现了key1同,key2不同的数据,而改动的地方在table1中居然没有体现!当然这不是重点,表中数据已经太多了,我们不能随便改动表,只能想别的方式。

找到问题所在,直觉反应就是加上distinct,想了一下应该没错,就改好sql在库中首先测一下,sql如下

select a,b,(select distinct c from table1 where ..) c from table2.. where..

问题来了,本来执行本条sql只需要4、5秒钟,结果这次执行了将近十分钟才执行完,如果不是我在执行的时候又检查了一遍sql发现没错,我都要直接停掉了。在执行期间上网查了一下,原来distinct需要排序然后才能去重,数据量小的时候没有什么影响,一旦数据量大了,就非常影响性能。没有什么太好的办法,只能用了一个取巧的办法, 因为查出来的c如果有重值的话都是相同的,所以就直接取第一行数据,sql如下:

select a,b,(select c from table1 where .. and rownum=1) c from table2.. where ..

改好测试,发现跟原来执行效率差不多,暂时就这样了。但是这里刚好能够取巧,如果多值不同的话distinct绕不过了,不知道有没有办法解决这个问题。不得不吐槽一下,表的设计太不合理了。

ps:这里要用这种查询方式的原因是需要table1中的c字段,而由于table1表太大,不想联查,只有在前端页面选择某项时才联查,这样在sqlmap中,用<isGreaterEqual>加table1 t,而c字段又不能直接写t.c,只能用以上sql重新查一下了。

-------

还有另外一个问题要吐槽一下,新需求要把web页面的某个查询条件从两种细分成5种,本来表中只用0和1表示,其他状态只能联查其他表,这个还好说,无非where语句里面细分,但是要在选择web页面选择全部的时候在list页面也要体现,这样只能在select里面用case when再查一遍了,这样直接加了四个查询,这样整个sql变的很臃肿,很担心以后再有新需求改动这里的时候其他人能不能看懂啊。

猜你喜欢

转载自lienhe.iteye.com/blog/2026643