mysql中變相解決排名問題,有點厲害

2021-01-07 IT大叔老韓的生活

為大家熟知的關係型資料庫有mysql、SQLServer、oracle、DB2等。它們的sql語句其實是有細微的差別的,不要想著有些語句在SQLServer上可以用就可以在mysql上使用。今天老韓就來講一下其中的一個知識點,mysql中如何排名。

SQLServer和oracle中有row_num函數,可以對資料庫中信息進行排名,但是mysql中卻沒有這個函數,那麼在mysql中如何解決這個問題呢,下面老韓分為兩塊來講解這個問題。

一、直接排序編號;

老韓想對student學生表中的學生按照score來進行排名,有些讀者朋友說了,直接用order by一下不就完了,這樣是按照成績排名了,但是並沒有編號,所以僅僅使用order by相當於需求實現了一部分,而且是很少的一部分,廢話不多說直接上SQL語句:

set @nub:=0;

select (@nub:=@nub+1) as 排名,a.* from student a order by score;

執行結果:可以看到已經實現了需求,既排序了,又有了排名欄位,咱們來分析一下SQL語句,set是賦值,還有一個賦值的關鍵字是select,但是使用select時候就不能直接將上面SQL語句中的set直接替換為select,因為select必須和select語句結合來使用,必須寫成:select @nub:=@nub+1 as 排名,b.* from (select * from student ) b, (select @nub:=0) c order by score

「@」是聲明變量的意思,除了「@」還有「@@」,兩個@符號表示是全局變量,一個@符號表示局部變量,mysql中也可以使用declare聲明變量,但是在這不可以使用,後面存儲過程章節,老韓會講,就跟Java中的new關鍵字一樣,「:=」表示賦值,這個地方等同於「=」,由於「:=」比「=」使用範圍廣泛,統一使用「:=」即可,@nub:=@nub+1表示@nub先+1再賦值給@nub,這個地方是前面老韓講過的虛擬列,這裡不多做贅述。

二、分組後再排序編號;

直接上SQL語句,老韓再針對SQL語句進行分析,SQL語句:

select

@nub:=(case when @classnoCopy=classno then @nub+1 else 1 end ) as 排名,c.*,@classnoCopy:=c.classno

from

(select b.* from (select distinct classno from student order by classno)a left join student b on a.classno = b.classno) c ,(select @nub:=0, @classnoCopy:=0 )d

查詢結果為:如下圖所示,可以看到實現了我們的需求。

先對學生進行分組再通過score來排名,老韓針對上面的sql語句來進行一個分析,分析一個sql語句的時候先從內往外分析,因為執行的時候也是從內而外,有人會問你為啥知道,如果內部不執行,外部如何查數據,肯定是內部先出來數據之後,外部才能去查。

最下面的別名為d的數據集,這個地方前面已經講過,聲明兩個變量並賦值。

別名為c的數據集,這裡面有個關鍵字distinct,表示去重,實際上不寫也沒問題但是老韓為了更明顯就寫了,表示取student表中所有的班級編號並去重,加上left join表示以班級為主表來進行數據填充,因為老韓又加了order by classno表示升序排列,那麼所有的信息都會以這個順序去匹配,效果如下圖所示;

加上left join之後的效果如下圖所示,如果不能理解為什麼是這種效果可以查看前面的左連接、右連接章節,其實這個地方完全可以寫成select username,classno,score from student order by classno,這裡是趕巧了可以直接使用order by,如果是字符串就不好說了。

最關鍵的地方來了,@nub:=(case when @classnoCopy=classno then @nub+1 else 1 end ) as 排名,c.*,@classnoCopy:=c.classno這兩句代碼如何理解呢?我們要明確一點,sql執行就想Java程序main方法中代碼執行一樣,從上到下去執行,先執行@nub:=(case when @classnoCopy=classno then @nub+1 else 1 end ) as 排名。

這裡面有個case when 語句,讀者朋友不要懵逼,這個東西其實我們前面學過的,它表示當classnoCopy=classno返回true的時候@nub=@nub+1,else就是返回false,@nub=1,最後以end結尾,表示語句結束,是不是跟三元運算非常相似啊,其實mysql中也有三元運算但是寫法跟Java中不一樣,所以上面的語句可以寫成這樣:@nub:=if(@classnoCopy=classno,(@nub+1),1),if(),瓜號內有三個變量,第一個變量就是表達式,返回一個boolean類型,後面跟兩個值,如果是true就返回第一個值,如果false就返回第二個值。

sql語句執行是從這一句開始執行的,可以看到,剛開始@classnoCopy是0,很明顯跟班級編號不一樣,那麼這個時候排名等於1,開始執行下面的語句,下面的語句是賦值,將classno賦值給@classnoCopy,sql語句是一行一行對結果集進行掃描的,到第二行的時候,@classnoCopy=classno很明顯是成立的,所以排名會加1變成2,掃描第三行的時候@classnoCopy=classno不成立了,因為這個時候@classnoCopy是1,classno是2,排名又變成了1,循環執行語句就得到需要的結果。

今天的內容就到這裡,如果不好理解的話就按照老韓寫的分析,一點一點來看,肯定可以搞懂。實際工作中就是這樣,需求是多種多樣的,mysql中確實沒有rownuber和rank函數,但是業務部門確實有這個需求,那麼只能用別的方式來變通實現,不管怎麼樣,抓到了老鼠就是好貓。如有問題可以通過上面的圖片和老韓取得聯繫,老韓知無不答。

沒有點關注的朋友,沒有點擊關注的朋友可以點波關注,你們每一次的關注、轉發、收藏都是老韓持續更新的動力,我是老韓,希望讀者朋友每天都能學到不一樣的IT知識,謝謝觀看,我們下期再見。

相關焦點

  • Mysql分區(PARTITION)實戰--解決Mysql大量刪除數據效率低的問題
    但是應用只需要保留1個小時內的數據,時間戳超過一個小時的數據要刪除掉。剛開始的時候採用一條一條刪除的方法,每5分鐘刪除一次,每次清除一個小時前的數據。但是遇到一個問題是,經常返回錯誤「Lock wait timeout exceeded; try restarting transaction」。發現mysql的netmon_history這張表被鎖定了。
  • MySQL裡面的group by問題淺析
    今天做一個備份看板的時候,無意中寫了如下的SQL,當時看到之後就有點疑惑了。
  • MySQL8.0窗口函數做數據排名統計詳細教程
    MySQL8.0新增了窗口函數,大大的方便了做數據排名統計的人,很多朋友還不清楚怎麼用MySQL8.0做數據統計排名,下面就來為大家分享一篇心得文章。
  • 搞定MySQL安裝難安裝貴問題
    背景本方案解決了windows下安裝MySQL過程繁瑣的問題。是真正的免安裝綠色方法,不用配環境變量,不用執行install命令,不用配置my.ini文件。>命令成功生成data目錄,同時生成無密碼的root用戶啟動MySQLbin下執行mysqld--console設置root密碼執行mysql-uroot-p連入資料庫,密碼不用輸入,直接按回車進入mysql>
  • 第09期:有關 MySQL 字符集的亂碼問題
    那麼數據亂碼問題在這兒顯得就非常簡單了,或許說可能不會出現這樣的問題。數據之所以會亂碼,在 MySQL 裡無非有以下幾類情況:在數據寫入到表的過程中轉碼失敗,資料庫端也沒有進行恰當的處理,導致存放在表裡的數據亂碼。針對這種情況,前幾篇文章介紹過客戶端發送請求到服務端。其中任意一個編碼不一致,都會導致表裡的數據存入不正確的編碼而產生亂碼。
  • 幾個常見而嚴重的 MySQL 問題分析 | 運維進階
    很多時候發生資料庫報錯時,不一定就是資料庫的問題,不一定非得急著呼叫資料庫人員解決。我們要形成這樣一種意識,我們不只是寫應用的,我們是寫金融系統的,我們理應具備一定的問題排查解決能力。本文將抽取幾個常見而嚴重的MySQL問題進行分析,並給出深度解答。藉以大家幫助思考。
  • 怎樣在vc、delphi中使用mysql
    怎樣在vc、delphi、vb等程序中使用mysql呢(mysql odbc驅動程序的使用)?我們經常會遇到這樣問題,怎樣在非web程序或asp程序中使用mysql資料庫呢?對於這個問題有兩個解決方案:   1、使用mysql提供的api函數庫。
  • MySQL問題兩則
    當時由於不在現場,了解到的信息只有:DDL語句腳本中只有兩條DDL語句,且都是添加欄位的語句。腳本正常運行只需要40-70秒。當時並不是停業窗口。考慮到資料庫版本為5.6.34,添加欄位並不會阻塞DML操作,讓開發小夥伴再運行一次試試,結果這次執行成功了,並沒有報衝突的錯誤。線上問題順利解決,具體原因得線下分析了。
  • 由一條create語句的問題對比mysql和oracle中的date差別 (r7筆記第26天)
    ,部署使用的環境是5.5這個時候手頭有一套虛擬機測試環境,立馬實驗了一下,發現在5.6中竟然沒有任何問題。這部分內容在MySQL官方文檔中也有說明。http://dev.mysql.com/doc/refman/5.0/en/data-type-defaults.html那麼這個問題還是需要解決,怎麼解決呢。首先不可能為了這個操作先把資料庫升級到5.6那麼解決方法就有兩個。
  • MySQL Time Zone 時區問題
    在啟動時可以使用命令行上的--default-time-zone = timezone選項顯式指定初始全局伺服器時區值,也可以在選項文件中使用以下行:default-time-zone='timezone'例如:可以通過修改my.cnf在 [mysqld] 之下加default-time-zone
  • Mysql資料庫update操作死鎖問題分析
    簡介問題是這樣的,我負責的一個線上模塊的功能是給裝有我們產品APP的手機設備根據業務功能打上特殊的推送標籤。每個設備有多個不同的標籤,每個標籤下包括很多設備。由於用戶在使用app時會觸發很多邏輯,隨時都可能有對標籤的增刪。
  • MySQL中只會count(),sum()?累加運算沒聽過?
    這個統計sql還是花了我一小段時間的。mysql統計這個還是需要一定的技巧的。下面才是我們想要的結果:reg_timedaily_quantity2019-09-0312019-09-0432019-09-0552019-09-066 這就有點棘手了,我們需要進行累加計算。
  • mysql中count()太慢,我該怎麼辦
    資料庫中每個表行數,對應redis中的一個key的值。每當向其中一個表增加1行數據時,redis中對應key的值就增加1,每當表中刪除1行數據時,redis中對應key的值就減1。而且在redis中進行讀寫的效率都很高,看似很完美的一個方案。卻存在以下兩個問題:1.redis本質上是一個緩存,可能存在數據丟失。
  • MySQL sql_mode 說明(及處理一起 sql_mode 引發的問題)
    不說開發的問題,好端端的mysql怎麼突然就部分表寫入失敗呢?根據上面的問題很快能猜到是 sql_mode 問題: NOT NULL 列沒有默認值但代碼裡也沒給值,在非嚴格模式下,int列默認為0,string列默認為』』了,所以不成問題;但在嚴格模式下,是直接返回失敗的。
  • Linux運維遇到的基本問題解決大全
    那針對這個問題,我們怎麼解決呢?可能原因1:Linux作業系統配置比較低,導致Linux無法啟動,調整CPU與內存配置可能原因2:VMware15版本與Windows10作業系統有點不兼容解決方案:降低VMware軟體版本,建議使用VMware12版本
  • 讓MySQL與OpenOffice共舞
    我把libodbc.so從/usr/local/lib拷貝到/usr/lib後,問題就解決了。於是,一切都正常了。圖2是OpenOffice的表設計窗口,在這個窗口中,我很容易就完成了一個表的設計,真是太棒了。雖然已經成功,但是我還是不覺得輕鬆,畢竟這個方法過於複雜。於是,我開始尋求更簡單的解決辦法。工夫不負有心人,最後,我終於找到了解決的辦法,也就是我將要給大家介紹的方法二。
  • 來談談MySQL事務及事務引發的問題
    持久性(Durability):持久性是指一個事務一旦被提交,它對資料庫中數據的改變就是永久性的,不能再回滾。事務有這些特性,但是他又帶來了什麼樣的問題呢?既然使用事務有這些問題,那我們應該怎麼解決呢?在這裡說一下mysql的事務隔離級別事務的隔離級別在資料庫操作中,為了有效保證並發讀取數據的正確性,提出的事務隔離級別,在標準SQL規範中,定義了4個事務隔離級別,不同的隔離級別對事務的處理不同。
  • mysql大表中count()的用法以及mysql中count()的優化
    本篇文章給大家帶來的內容是關於mysql大表中count()的用法以及mysql中count()的優化,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。一個單表中包含有6000w+的數據,然而你又不能拆分.需要分別統計表中有多少數據,A產品有多少,B產品有多少這幾個數據.
  • 杜特爾特這招厲害了!欲借中國解決菲律賓10萬英語教師的就業問題
    杜特爾特這招厲害了!欲借中國解決菲律賓10萬英語教師的就業問題!在中國香港等地,許多家庭都會僱菲傭當家傭,巔峰時期,光香港一地僱傭的菲傭就達到了15.5萬人,因此菲傭也成為了菲律賓的代名詞。據不完全統計菲律賓在海外工作的勞務人員達到了240萬,佔到了總人口2.4%,這些勞務人員中不僅有菲傭,還有許多服務類,製造類的工人,其中有一個最特別的軍事英語老師,可能你會覺得很詫異,菲律賓英語老師能行嗎?專業水平怎麼樣呢?
  • 在MySQL中使用XML數據—數據格式化
    在這個例子中,使用Prepared Statement的好處是可以設置標題,然後連接到我們的查詢字符串中。 +-----------+| client_id |+-----------+| 2           |+-----------+  在存儲過程中使用ExtractValue()函數  上面使用的方法最大的缺陷就是在代碼中寫死了要檢索的行,這樣很不靈活,下面我們使用一個存儲過程來解決這個問題