1. 程式人生 > 其它 >MYSQL 和 MYBATIS 對查詢出的結果集 增加 自增 序號列/排序列

MYSQL 和 MYBATIS 對查詢出的結果集 增加 自增 序號列/排序列

目錄

今天做了一個關於排行榜的功能

參考一:

第一種方法:

第二種方法:

參考二:

對於  變數  i  的分析: 

參考三(很全面易懂):

一、變數的定義及使用

二、變數的賦值

三、變數使用小技巧

參考四:

問題一

問題二

參考五:(允許出現同名次:出現並列的名次,比如出現兩個第二名,接著就是第四名)

參考六(最全最詳細的):


今天做了一個關於排行榜的功能

大概就是對粉絲總數的值進行倒序排序,取粉絲數最多的前一百名,需要返回對應的名次;

這裡特殊說明一下,如果粉絲數相同,則按達到條件時間的先後排序,不允許出現名次相同的現象;

我這就直接上程式碼了啊,邏輯什麼的大家自己看看就行,具體的解釋 在下面的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可以正常的查詢 出來資料.


參考五:(允許出現同名次:出現並列的名次,比如出現兩個第二名,接著就是第四名)

  1.   按分數統計排名查詢怎麼寫,比如user表如下:
  2.   id 分數(grade)
  3.   1 90
  4.   2 87
  5.   3 87
  6.   4 80
  7.   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總變數不用事先宣告,在用的時候直接用@變數名 使用即可