在大多數應用場景下,我們使用mysql進行查詢時只會用到'=', '>' , '<' , in, like 等常用的方法,看起來,大多數情況下,已經足以應付我們的小型應用了。不過,在一些特殊場景,則需要特殊的查詢方式了。
1. 根據狀態來排序的查詢
假設現在一個記錄有四種狀態,未處理(0)、正在處理(2)、處理成功(1)、處理失敗(4),之所以他們的值是這個樣子,是因為我們一般情況下是不會用它去排序,所以自然的就想到這樣的一些值賦予意義。但是,在排序的時候怎么處理呢? 假如要求的先后順序是這樣的:未處理>處理失敗>正在處理>處理成功, 我能想到的就是,假設它們這些狀態就是按照要求的排序的值去依次增加的,那就只需要一個order by 該字段即可。具體實現如下:
select * from tab_task b order by (CASE b.deal_status WHEN 0 THEN 10 WHEN 2 THEN 30 WHEN 1 THEN 40 WHEN 4 THEN 20 ELSE 40 END) ASC,b.add_time desc //按照所需排序值,依次賦值
如果是要根據某個計算的值來排序,如按平均成績排序,則實現如下:
SELECT * FROM score b GROUP BY uid ORDER BY AVG(b.`score`) DESC; //直接計算得出排序值,使用RAND()可以得到隨機的排序
2. 比較復雜的模糊查詢
有時,我們需要從某字段中篩選符合條件的值,但是該值又不是一個獨立的字段,這時就需要一些高級的模糊查詢(正則)。
如,需要查詢某個值大於0的記錄,實現如下:
SELECT * FROM tab_day_data WHERE retention_days_full REGEXP '.*rd1=([0][1-9]+|[1-9][0-9]*).*'; //查詢rd{x}大於0的記錄,其中rd可能是許多個類似的不重要的值,被儲存至一個字段,同理於其他
mysql正則語法,如下:
// . 表示匹配任意一個字符 // | 作為OR操作符,表示匹配其中之一 // [ ] 匹配任何單一字符 // [:a;num:] 任意字母和數字(同 [a-zA-Z0-9]) // [:alpha:] 任意字符(同 [a-zA-Z]) // [:blank:] 空格和制表(同 [\\t]) // [:cntrl:] ASCII控制字符(ASCII 0到31和127) // [:digit:] 任意數字(同[0-9]) // [:graph:] 與["print:] 相同,但不包括空格 // [:lower:] 任意小寫字線(同 [a-z]) // [:print:] 任意可打印字符 // [:punct:] 既不在 [:alnum:] 又不在 [:cntrl:] 中的任意字符 // [space:] 包括空格在內的任意空白字符(同 [\\f\\n\\t\\r\\v]) // [:upper:] 任意大小字母(同 [A-Z]) // [:xdigit:] 任意十六進制數字(同 [a-fA-F0-9]) // 元字符 .*?+{m}{m,}{m, n}
語法與正宗的正則不太一致,但大體原理是一致的。
用mysql做復雜的匹配,雖然可以實現,但是相對來說效率低下,最好還是使用獨立字段的形式進行查詢,用空間換取時間!
3. 檢查校驗和,驗證表是否相等
數據在傳輸時,可能會發生變化,也有可能因為其它原因損壞,為了保證數據的一致,我們可以計算checksum(校驗值)。
使用MyISAM引擎的表會把checksum存儲起來,稱為live checksum,當數據發生變化時,checksum會相應變化。
CHECKSUM TABLE tbl_name [, tbl_name] ... [QUICK | EXTENDED]
附:mysql進程查看,卡死現象的解決辦法
SHOW FULL PROCESSLIST; # 查看所有的進程情況,具體解決請百度 SHOW STATUS; # 查看總體運行概況 KILL 213; # 將運行慢或卡死的進程刪除,注意數據的事務性,否則可能導致數據錯誤
問?
mysql 分表之后(比如按年分表,多個相關聯表同步拆分),查詢應該怎樣做才好?