MYSQL 和 MYBATIS 對查詢出的結果集 增加 自增 序號列/排序列
目錄
參考五:(允許出現同名次:出現並列的名次,比如出現兩個第二名,接著就是第四名)
今天做了一個關於排行榜的功能
大概就是對粉絲總數的值進行倒序排序,取粉絲數最多的前一百名,需要返回對應的名次;
這裡特殊說明一下,如果粉絲數相同,則按達到條件時間的先後排序,不允許出現名次相同的現象;
我這就直接上程式碼了啊,邏輯什麼的大家自己看看就行,具體的解釋 在下面的6個參考中:
<select id="rankFansList" resultType="java.util.HashMap">
select
@rownum:=@rownum+1 as rowNum ,
amount,
userId,
userName,
avatarUrl,
rankFlag
from
(select @rownum := 0) as rownum,
(select
count(uor.user_id) as amount,
uor.source_id as userId,
case uor.source_id when #{userId} then 1 else 0 end as rankFlag,
<if test="userType != null and userType == 1">
up.nick_name as userName,
up.avatar_url as avatarUrl
</if>
<if test="userType != null and userType == 2">
ut.nick_name as userName,
ut.avatar_url as avatarUrl
</if>
<if test="userType != null and userType == 3">
ui.nick_name as userName,
ui.avatar_url as avatarUrl
</if>
from user_operate_record uor
<if test="userType != null and userType == 1">
left join user_parent up on uor.user_id = up.user_id
</if>
<if test="userType != null and userType == 1">
left join user_teacher ut on uor.user_id = ut.user_id
</if>
<if test="userType != null and userType == 1">
left join user_institution ui on uor.user_id = ui.user_id
</if>
where uor.handle_type = 4 and uor.praise_status = 1 and uor.source_user_type = #{userType}
and (
uor.create_time between unix_timestamp(date_format(NOW(), '%Y-%m-01')) and unix_timestamp(date_format(last_day(curdate()), '%y-%m-%d 23:59:59'))
or
uor.update_time between unix_timestamp(date_format(NOW(), '%Y-%m-01')) and unix_timestamp(date_format(last_day(curdate()), '%y-%m-%d 23:59:59'))
)
group by uor.source_id
order by count(uor.user_id) desc,uor.create_time desc
) k
where k.amount > 0
</select>
以下是我在網上找到的一些相關資料:
參考一:
https://blog.csdn.net/qq_34365173/article/details/80869475
第一種方法:
select (@i:=@i+1) as i,user_manage.* from user_manage,(select @i:=0) as it ;
@i:=@i+1 as i 會生成一個排序的i,在查詢的時候,會在結果集中顯示,@i:0 的意思是i從1開始排序。
第二種方法:
set @rownum=0;
select @rownum:=@rownum+1 as rownum, t.name from user_manage t;
參考二:
https://blog.csdn.net/arbben/article/details/78665389
對於 變數 I 的分析:
在開始是定義一個變數i,讓它每增一條結果是 +1,@i:=1;
這裡順帶複習下mysql定義使用者變數的方式:select @變數名
對使用者變數賦值有兩種方式,一種是直接用”=”號,另一種是用”:=”號。其區別在於使用set命令對使用者變數進行賦值時,兩種方式都可以使用;當使用select語句對使用者變數進行賦值時,只能使用”:=”方式,因為在select語句中,”=”號被看作是比較操作符
(@i:=@i+1) 也可以寫成 @i:=@i+1,加括號是為了視覺上看這結構更清楚些。在定義好一個變數後每次查詢都會給這個變數自增,而我們每次執行查詢語句獲取結果後就不需要這個變數自增了,所以要把它重置為0,在表名後用逗號分格下使用 (SELECT @i:=0) as i 就可以了,說下這個as i為什麼要這樣用,是因為派生表必須需要一個別名,這個就是做它的別名,可以任意字元。
參考三(很全面易懂):
https://blog.csdn.net/qq_38377190/article/details/98488030
SQL語句定義變數,如下:
-- 定義變數並賦值
SET @c = '2333';
-- 查詢定義的變數的值
SELECT @c;
執行結果
2333
那麼如何在mybatis的框架實現變數的定義的呢?如果能實現變數的定義,那就可以在mybatis上寫一定量的業務程式碼,也是不錯的!
一、變數的定義及使用
<update id="updatePrice">
/*1.變數定義*/
select @isEnd := 0, @isFinish := 1;
/*2.使用變數*/
update Sc_Stock a set a.cost_price = 10 where @isFinish= 1 and @isEnd = 0;
</update>
二、變數的賦值
<update id="updatePrice">
/*1.變數定義*/
select @newPrice:=0;
/*2.變數賦值*/
update Sc_Stock a set a.price = @newPrice := 11 where a.id = 2222;
/*3.變數使用*/
update Sc_Stock a set a.num = 2 where @newPrice = 11;
</update>
三、變數使用小技巧
<update id="updatePrice">
/*1.變數定義*/
select @isFinish:=0;
/*2.變數使用*/
update Sc_Stock set num = 2 where newPrice = 11 and if(@isFinish = 0, 0, @isFinish := a.is_finish);
</update>
解釋一下:上方更新語句最後會變成
update Sc_Stock set num = 2 where newPrice = 11 and 0;
或是
update Sc_Stock set num = 2 where newPrice = 11 and 1;
參考四:
mybatis中使用sql變數:https://blog.csdn.net/qq_28736639/article/details/101553522
需求背景
在一個這樣的業務中,需要查詢一個表A的記錄,其中A表的主要欄位有 id , createtime ,amount ,現在要求給定一個數字N,查詢按照建立時間順序排列之後的前 x條記錄,這x條記錄需要滿足sum(amount)>=N並且儘可能的小的條件。其中傳入的引數只有N。在這種情況下,筆者第一個想到的方案就是在sql中使用變數來記錄這個sum(amount)的值來達到目的。其中sql如下:
-- 這個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可以正常的查詢 出來資料.
參考五:(允許出現同名次:出現並列的名次,比如出現兩個第二名,接著就是第四名)
- 按分數統計排名查詢怎麼寫,比如user表如下:
- id 分數(grade)
- 1 90
- 2 87
- 3 87
- 4 80
- 5 79
需求:出現並列的名次,比如出現兩個第二名,接著就是第四名
select
id,
grade,
ifnull( (select count(*) from testSort where grade > t.grade),0 ) +1 as rankValue
from testSort t
結果:
參考六(最全最詳細的):
https://www.cnblogs.com/northern-light/p/8494711.html
----------------------------------------------另一篇文章
在hive和oracle等資料庫中,我們有開窗函式row_number可以快速便捷的生成序號。但是在mysql中,似乎不那麼容易實現。其實在MySQL中一樣可以實現。
話不多說,先上程式碼!!!
SELECT
a.*, @rank :=@rank+1 as no
FROM( ]
SELECT *
from `student_score_table`
ORDER BY `score` desc
) a
LEFT JOIN (
SELECT @rank :=0
) b
on 1 = 1
首先,需要先定義一個變數rank,然後與排序好的資料表做關聯,依次做自增就好。
這裡簡單介紹一下MySQL中變數的定義:
使用set或select直接賦值,變數名以 @開頭
賦值符號:使用set 時可以用 “=“或者“:=” 但是使用select賦值時必須使用“:=”賦值
mysql總變數不用事先宣告,在用的時候直接用@變數名 使用即可