今天同事給了一個小需求,從一個存有不定數量座標數據的表(map_trace)中每隔20條取一條。最後寫了下面這條SQL:mysql
select * from (select @n:=@n+1 as n, a.* from (select * from map_trace order by CREATE_time desc)a,(select @n:=0)b)c where c.n%20<2 and c.n%20!=0;sql
在此複習下相關知識:數據庫
生成一個字段(非表中字段)用以記錄排序 (類比爲oracle數據庫中的rownum)oracle
MySQL中一個表(表名:stuscore),字段有:id(主鍵)、stuid(學號)、sname(學生姓名)、subject(課程名稱)、score(分數)ui
列出數學成績排名 (要求顯示字段:排名,姓名 , 課程名稱, 分數 , 學號)code
用於排名的字段,查詢時此處將其用 pm表示blog
select (@i:=@i+1)pm,s.* from stuscore s,(select @i:=0)t where s.subject='數學' order by score desc;排序
思想:事先定義一個變量i,經過變量遞加以及虛擬表的聯查達到生成序列號的目的。作用域
這裏,在開始是定義一個變量i,讓它每增一條結果是➕1,@i:=1;
這裏順帶複習下mysql定義用戶變量的方式:select @變量名。數學
對用戶變量賦值有兩種方式,一種是直接用"="號,另外一種是用":="號。其區別在於使用set命令對用戶變量進行賦值時,兩種方式均可以使用;當使用select語句對用戶變量進行賦值時,只能使用":="方式,由於在select語句中,"="號被看做是比較操做符(@i:=@i+1),也能夠寫成@i:=@i+1,加括號是爲了視覺上看這結構更清楚些。在定義好一個變量後每次查詢都會給這個變量自增,而咱們每次執行查詢語句獲取結果後就不須要這個變量自增了,因此要把它重置爲0,在表名後用逗號分格下使用 (SELECT @i:=0) as i
就能夠了,說下這個as i爲何要這樣用,是由於派生表必須須要一個別名,這個就是作它的別名,能夠任意字符。
select * from table1,table2 不加任何條件時,是把兩個表的數據笛卡爾積以後顯示,如上sql中的 t 這張表 其實就是 一條 i=0 的數據
mysql存儲過程當中,定義變量有兩種方式:
一、使用set或select直接賦值,變量名以 @開頭
賦值符號:使用set 時能夠用 「=「或者「:=」 可是使用select賦值時必須使用「:=」賦值
例如: set@id=1;能夠在一個會話的任何地方聲明,做用域是整個會話,稱爲會話變量。mysql總變量不用事先聲明,在用的時候直接用@變量名 使用便可
【先行記錄】
二、以 DECLARE 關鍵字聲明的變量,只能在存儲過程當中使用,稱爲存儲過程變量,例如:
DECLARE var1 INT DEFAULT 0;
主要用在存儲過程當中,或者是給存儲傳參數中
二者的區別是:
在調用存儲過程時,以DECLARE聲明的變量都會被初始化爲 NULL。而會話變量(即@開頭的變量)則不會被再初始化,在一個會話內,只須初始化一次,以後在會話內都是對上一次計算的結果,就至關於在是這個會話內的全局變量。在存儲過程當中,使用動態語句,預處理時,動態內容必須賦給一個會話變量。
例: set @v_sql= sqltext; PREPARE stmt FROM @v_sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;