前言:这段时间搞mongodb的项目去了,关系型数据库的使用又生疏了。火速捡起开学!罪过啊!
1.初见!
今天发版,顺带就看看生产环境的数据是否正常。结果发现一个巨离谱的数据,大概就像记录一个人的身高,别人机械自动测量出来是999cm,数据传给我们后我们的界面就直接就展示了。
额~于是马上加上数据清洗,把机械自动测量的数据先去除掉再返给前端。
2.再见!!
美滋滋改完自测后又发了一版,线上又看了下。有几个接口按预期进行了数据清洗返回了,但是身高999cm的这哥们又跑出来了,wtf?
来来来,改错题来了,各位看官请看题:
SELECT
<include refid="Base_Column_List_E667"/>
FROM EVENT E667
<where>
AND E667.EVENT_FROM != '1'
<if test="timeStampCode != null">
AND (#{timeStampCode} = 1 AND E667.O_TIME between add_months(now(),-1) and now())
OR
(#{timeStampCode} = 2 AND E667.O_TIME between add_months(now(),-1*6) and now())
OR
(#{timeStampCode} = 3 AND E667.O_TIME between add_months(now(),-1*12) and now())
</if>
</where>
问题:当timeStampCode为1时,能正常查出eventFrom不为1的数据,但是为2时就会出现eventFrom为1的数据。怪,我明明把AND E667.EVENT_FROM != '1'写在最前面了哇!这是为什么捏?
而且明明AND的优先级比OR高啊,百思不得其解。
罚你重新去学sql! 罚你重新去学sql! 罚你重新去学sql!
3.解析
看似这样没问题,但当timeStampCode为2时,会生效该条件:
(#{timeStampCode} = 2 AND E667.O_TIME between add_months(now(),-1*6) and now())
然而实际上该条件是通过 'OR' 连接到其他条件上的,而不是 'AND' 。所以,虽然AND E667.EVENT_FROM != '1'仍然存在,但它与其他条件没有逻辑连接,所以导致失效。
如何解决呢?
在条件之间加上括号即可,明确它们之间的逻辑连接关系。
以下是修正后的sql:
SELECT
<include refid="Base_Column_List_E667"/>
FROM EVENT E667
<where>
AND E667.EVENT_FROM != '1'
<if test="timeStampCode != null">
AND (
(#{timeStampCode} = 1 AND E667.O_TIME between add_months(now(),-1) and now())
OR
(#{timeStampCode} = 2 AND E667.O_TIME between add_months(now(),-1*6) and now())
OR
(#{timeStampCode} = 3 AND E667.O_TIME between add_months(now(),-1*12) and now())
)
</if>
</where>
还有种方法是在每个or语句后面都加上AND E667.EVENT_FROM != '1',但这样的后果是如果timeStampCode不符合条件时,where子句将为空,导致整个查询结果为空。
本人才疏学浅,各位就当看个乐子。再问就是yyz,哼