mysql如何按首字母進行檢索數(shù)據(jù)
一、介紹
最近有個這樣的需求,一張有大量數(shù)據(jù)元素的表,這里就暫且舉例為 student 表,現(xiàn)在要按照學生的首字母來進行檢索學生信息。
比如用戶輸入“ZS”,獲得的學生列表的姓名第一個字拼音以“Z”開頭,第二個字以“S”開頭。
我想這個應該大家都明白什么需求,對于這個需求我之前項目中沒有遇到過,至于有沒有一些搜索系統(tǒng)或者第三方解決這個問題,我不太清楚,下面是我就這個需求進行的實現(xiàn),也為以后自己遇到類似需求做參考。
二、分析
以首字母來查詢有兩種情況:
1、可以增加表字段,即將student表中添加一個firstwords字段來記錄學生名的首字母,這樣就可以直接拿此字段進行模糊匹配檢索(name:“張三”,firstwords:"ZS")。
2、不能增加表字段,工作中很多表或者數(shù)據(jù)庫都是客戶的或者是長時間不動的表,基本不建議修改的情況,無法增加首字母的相關字段,此時就需要用代碼來實現(xiàn)此需求。
這里只介紹第二種情況的實現(xiàn),第一種情況太簡單就不說了。
三、實現(xiàn)
剛開始我看需求時,我上網各種查詢,發(fā)現(xiàn)很多方法都不能用或者說我用不好吧,不過通過閱讀網上各種方法,我自己總結了一個搜索方式,測試過沒發(fā)現(xiàn)什么問題。
我們知道數(shù)據(jù)庫查詢時可以排序查詢,比如ASC關鍵字排序,那么漢子是通過什么排序呢,最后通過網上查閱資料,如果存儲漢字的字段編碼使用的是GBK字符集的話,其采用的是拼音排序的方法,UTF-8的字符集目前我沒去研究,雖然mysql存儲數(shù)據(jù)基本都是utf-8,但可以在查詢的時候轉為GBK,一樣可以查詢,下面是A—Z的字符集對應漢子的范圍
static {
wordsMap = new HashMap<>();
wordsMap.put("a","45217,45252");wordsMap.put("b","45253,45760");wordsMap.put("c","45761,46317");
wordsMap.put("d","46318,46825");wordsMap.put("e","46826,47009");wordsMap.put("f","47010,47296");
wordsMap.put("g","47297,47613");wordsMap.put("h","47614,48118");wordsMap.put("j","48119,49061");
wordsMap.put("k","49062,49323");wordsMap.put("l","49324,49895");wordsMap.put("m","49896,50370");
wordsMap.put("n","50371,50613");wordsMap.put("o","50614,50621");wordsMap.put("p","50622,50905");
wordsMap.put("q","50906,51386");wordsMap.put("r","51387,51445");wordsMap.put("s","51446,52217");
wordsMap.put("t","52218,52697");wordsMap.put("w","52698,52979");wordsMap.put("x","52980,53640");
wordsMap.put("y","53689,54480");wordsMap.put("z","54481,55289");
}這是段代碼,代碼意思為每個首字母對應漢子的包含范圍,比如:首字母為“a”的漢子ASC編碼范圍都在45217和45252之間,有了這個信息基本上也就可以完成該需求了,下面是需求實現(xiàn)的代碼
FisrtWordsSqlUtils 這個Utils類是用來存儲漢子范圍和拼接sql語句用的
package com.oracle;
import java.util.HashMap;
import java.util.Map;
/**
* @author WYH
*/
public class FisrtWordsSqlUtils {
//依次從小到大排序
private static Map<String,String> wordsMap;
static {
wordsMap = new HashMap<>();
wordsMap.put("a","45217,45252");wordsMap.put("b","45253,45760");wordsMap.put("c","45761,46317");
wordsMap.put("d","46318,46825");wordsMap.put("e","46826,47009");wordsMap.put("f","47010,47296");
wordsMap.put("g","47297,47613");wordsMap.put("h","47614,48118");wordsMap.put("j","48119,49061");
wordsMap.put("k","49062,49323");wordsMap.put("l","49324,49895");wordsMap.put("m","49896,50370");
wordsMap.put("n","50371,50613");wordsMap.put("o","50614,50621");wordsMap.put("p","50622,50905");
wordsMap.put("q","50906,51386");wordsMap.put("r","51387,51445");wordsMap.put("s","51446,52217");
wordsMap.put("t","52218,52697");wordsMap.put("w","52698,52979");wordsMap.put("x","52980,53640");
wordsMap.put("y","53689,54480");wordsMap.put("z","54481,55289");
}
/**
* 拼接sql
* @param str
*/
public static String getSql(String str){
String wordsStr = str.toLowerCase();
//排除該三個首字母,因為中文就沒有以他們開頭的拼音
if(str.contains("i")||str.contains("u")||str.contains("v")){
System.out.println("暫無數(shù)據(jù)");
return null;
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < wordsStr.length(); i++) {
String c = wordsStr.charAt(i)+"";
String wordsASC = wordsMap.get(c);
String[] asc = wordsASC.split(",");
int ASC01 = Integer.parseInt(asc[0]);
int ASC02 = Integer.parseInt(asc[1]);
if(i!=wordsStr.length()-1){
sb.append("CONV(HEX(SUBSTRING(CONVERT(name USING gbk ), "+(i+1)+",1)), 16, 10) BETWEEN "+ASC01+" AND "+ASC02 + " and ");
}else{
sb.append("CONV(HEX(SUBSTRING(CONVERT(name USING gbk ), "+(i+1)+",1)), 16, 10) BETWEEN "+ASC01+" AND "+ASC02);
}
}
return sb.toString();
}
}sql拼接代碼中:“CONV,HEX,SUBSTRING,CONVERT”這幾個是數(shù)據(jù)庫的一些函數(shù),整體意思先轉GBK編碼,然后截取某個位置字母,然后轉16進制的字符集,然后再由16進制轉10進制,最終得到的就是像那個hashmap集合里面的那一串數(shù)字。后面的between and 語句就不解釋了,這個不知道估計這篇文章也不會看的太不懂。
上面的sql語句已經可以得到,下面是mysql數(shù)據(jù)庫原生連接的方法
/**
* @author WYH
*/
public class MySqlConnectUtil {
public static Map<String,Object> getResultMap(String dbUser, String dbPwd, String orclUrl, String tableName,String mySql){
Map<String,Object> resultMap = new HashMap<>();
Connection con=null;
PreparedStatement pre=null;
ResultSet resultSet=null;
try{
Class.forName("com.mysql.jdbc.Driver");
con= DriverManager.getConnection(orclUrl,dbUser,dbPwd);
String sql="select * from "+tableName +" where " + mySql;
System.out.println(sql);
pre=con.prepareStatement(sql);
resultSet=pre.executeQuery();
resultMap = getResultMap(resultSet);
}catch(Exception ex){
ex.printStackTrace();
System.out.println("未能返回結果");
}finally{
JdbcUtil.release(con,pre,resultSet);
}
return resultMap;
}
private static Map<String,Object> getResultMap(ResultSet resultSet) throws SQLException {
Map<String,Object> reusltMap = new HashMap<>();
List<Map> maps = new ArrayList<>();
ResultSetMetaData rsmd = resultSet.getMetaData();
while(resultSet.next()){
int columnCount = rsmd.getColumnCount();
Map map = new HashMap();
for (int i = 1; i <= columnCount; i++) {
Object object = resultSet.getObject(i);
String columnName = rsmd.getColumnName(i);
String columnTypeName = rsmd.getColumnTypeName(i).toLowerCase();
if(columnTypeName.equals("date")&&columnTypeName.equals("time")&&columnTypeName.equals("timestamp")){
Date date = (Date) object;
long time = date.getTime();
map.put(columnName,time+"");
}else {
map.put(columnName, object);
}
}
maps.add(map);
}
reusltMap.put("data",maps);
return reusltMap;
}
}這個是連接數(shù)據(jù)庫的工具類,手寫的原生的,如果項目中使用第三方的如mybatis等可以不用,這里我寫這個也是為了測試使用,邏輯上看的更清晰一點。
下面是最終測試的方法
/**
* @author WYH
*/
public class TestFirstWordsSearcher {
public static void main(String[] args) {
String userName = "root";
String password = "root";
String oracleUrl = "jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=utf-8";
String tableName = "student";
try {
String sql = FisrtWordsSqlUtils.getSql("LS");
Map<String, Object> reusltMap =MySqlConnectUtil.getResultMap(userName,password,oracleUrl,tableName,sql);
String s = JSON.toJSONString(reusltMap);
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
}
}測試結果截圖如下:

文章核心點就是每個首字母對應的ASC編碼的范圍,利用此范圍進行拼接sql,然后查詢數(shù)據(jù)
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
mysql觸發(fā)器之創(chuàng)建使用觸發(fā)器簡單示例
這篇文章主要介紹了mysql觸發(fā)器之創(chuàng)建使用觸發(fā)器,結合實例形式分析了mysql創(chuàng)建、查看、調用觸發(fā)器的相關操作技巧,需要的朋友可以參考下2019-12-12
MySQL中預處理語句prepare、execute與deallocate的使用教程
這篇文章主要介紹了MySQL中預處理語句prepare、execute與deallocate的使用教程,文中通過示例代碼介紹的非常詳細,對大家學習或者使用mysql具有一定的參考學習價值,需要的朋友們下面跟著小編一起來學習學習吧。2017-08-08
django2.2版本連接mysql數(shù)據(jù)庫的方法
這篇文章主要介紹了django2.2版本如何連接mysql數(shù)據(jù)庫,本文圖文并茂給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10

