mybatis中使用sql变量

mybatis中使用sql变量

  • 需求背景
    • 问题一
      • 问题二

需求背景

在一个这样的业务中,需要查询一个表A的记录,其中A表的主要字段有 id , createtime ,amount ,现在要求给定一个数字N,查询按照创建时间顺序排列之后的前 x条记录,这x条记录需要满足sum(amount)>=N并且尽可能的小的条件。其中传入的参数只有N。在这种情况下,笔者第一个想到的方案就是在sql中使用变量来记录这个sum(amount)的值来达到目的。其中sql如下:
SET @sum =0;
SET @flag =0;
SELECT *
FROM (
SELECT
(CASE WHEN @sum < 100 THEN @sum := @sum + restpoints ELSE @sum := @sum +
restpoints END) AS sum,
(CASE WHEN @sum <100 THEN @flag :=0 ELSE @flag := @flag + 1 END) AS flag,
(CASE WHEN @flag < 2 THEN id ELSE NULL END) AS xxid,
(CASE WHEN @flag < 2 THEN restpoints ELSE NULL END) AS xxrestpoints,
t.*
FROM (select * from A) a
order by date(useexpiretime) asc,restpoints desc
)t
)AS TMP
WHERE TMP.xxid IS NOT NULL

问题一

遇到的问题就是mybatis似乎不支持上面的这种写法,会报语法错误,在确定这个sql在xml中没有书写错误的情况下,开始进行sql的一些变形,来尝试看是否可以。
第一个尝试就是把SET @sum =0;SET @flag =0; 去掉了,放在了 select 里面去定义,因为我发现,即使是只有SET语句也是会报错的,推测mybatis可能不支持SET。即变化如下:
	SELECT @sum:= 0,@flag := 0,TMP.*
	FROM (
	SELECT
	(CASE WHEN @sum < 100 THEN @sum := @sum + restpoints ELSE @sum := @sum +
	restpoints END) AS sum,
	(CASE WHEN @sum <100 THEN @flag :=0 ELSE @flag := @flag + 1 END) AS flag,
	(CASE WHEN @flag < 2 THEN id ELSE NULL END) AS xxid,
	(CASE WHEN @flag < 2 THEN restpoints ELSE NULL END) AS xxrestpoints,
	t.*
	FROM (select * from A) a
			order by date(useexpiretime) asc,restpoints desc	
	 )t
	)AS TMP
	WHERE TMP.xxid IS NOT NULL

这个时候发现,mybatis查询得时候不会报错了,很好,到这个时候基本问题就解决了。

问题二

但是紧接着就发现查询出来的数据都是空的,我使用日志打印出来的sql进行查询发现也是空的,但是使用之前未变形的那种是正常的,这时候可能就是flag 和sum的值 有问题了,我是用select @flag进行查看,发现它的值果然不是0,而是19,这让我感到很奇怪,就是说外层的赋值似乎不等同于SET这种赋值方式,仔细想想,嵌套查询的情况都是从子查询开始执行的,所以可能在里面的子查询开始的时候,外层的赋值并没有起到作用,所以,我把这个赋值作为一个单独的子查询放在了最里面,如下:
	
	SELECT @sum:= 0,@flag := 0,TMP.*
	FROM (
	SELECT
	(CASE WHEN @sum < 100 THEN @sum := @sum + restpoints ELSE @sum := @sum +
	restpoints END) AS sum,
	(CASE WHEN @sum <100 THEN @flag :=0 ELSE @flag := @flag + 1 END) AS flag,
	(CASE WHEN @flag < 2 THEN id ELSE NULL END) AS xxid,
	(CASE WHEN @flag < 2 THEN restpoints ELSE NULL END) AS xxrestpoints,
	t.*
	FROM (select * from A) a
			order by date(useexpiretime) asc,restpoints desc	
	 )t,(SELECT @sum:= 0,@flag := 0) notuse
	)AS TMP
	WHERE TMP.xxid IS NOT NULL

最终,这个sql可以正常的查询 出来数据.

你可能感兴趣的:(mybatis)