1. 程式人生 > >Mycat 實現MongoDB的BETWEEN AND和多IN&NOT IN查詢

Mycat 實現MongoDB的BETWEEN AND和多IN&NOT IN查詢

在實現過程中第一就是分析怎麼去實現,其次在mycat哪個部分實現。首先我們知道BETWEEN AND是一個區間值查詢,而IN 是一個多值且的關係,其實最終目的都是封裝為MongoDB支援的資料庫操作語句,如:db.getCollection('t_alarm_aggr_20170822').find({ "F_START_TIME" : { "$gte" : "2017-08-21 00:00:00" , "$lte" : "2017-08-23 23:55:00"} , "F_ID" : { "$in" : [5000000001064]}}); 這樣就實現了我們的需求了。

BETWEEN AND查詢

主要操作io.mycat.route.util.RouterUtil.java類:

	
	/**
	 * @throws SQLNonTransientException 
	 * 解析betweenSQL 
	 * @MethodName: parseSQLToChangeBetweenSql 
	 * @Description: 
	 * @param ctx
	 * @throws
	 */
	private static void parseSQLToChangeBetweenSql( DruidShardingParseInfo ctx) throws SQLNonTransientException{
	      if(ctx==null){
            return; // 沒有上下文:no route to find
        }
        String tempStr=new String(ctx.getSql().toString()).replaceAll(" ", "").toUpperCase().trim();
        String endSql="";
		if(tempStr.contains("NOTBETWEEN")){
			throw new IllegalArgumentException("Not support' WHERE $condition NOT BETWEEN $a AND $b ' sql statement :"+ctx.getSql());
		}else if(tempStr.contains("BETWEEN")){
			String sql=ctx.getSql().toUpperCase();
			String conditions=StringUtil.keepInnerSpaceStr(sql.substring(sql.indexOf("WHERE")+5, sql.length())); 
			String strs[] =conditions.split("AND");
			String conditionField="";
			String values[]=new String [2];
			int index=-1;
			for (int i = 0; i < strs.length; i++) {
				if(strs[i].contains("BETWEEN")){
					String temp=StringUtil.keepInnerSpaceStr(strs[i]);
					conditionField=temp.split(" ")[0];
					values[0]=temp.split(" ")[2]+" "+temp.split(" ")[3];
					values[1]=StringUtil.keepInnerSpaceStr(strs[i+1]);
					index=i;
					break;
				}
			}
			Date dates[]=new Date [2];
			for (int i = 0; i < values.length; i++) {
				try {
					dates[i]=DateUtil.parseDate(StringUtil.removeBackquote(values[i]), DateUtil.DEFAULT_DATE_PATTERN); 
				} catch (ParseException e) {
					throw new SQLNonTransientException("date time format must be:"+DateUtil.DEFAULT_DATE_PATTERN);
				}
			}
			StringBuffer changeSql=new StringBuffer();
			if(dates[0].getTime()<dates[1].getTime()){
				changeSql.append(conditionField+" >= "+values[0]).append(" AND ").append(conditionField+" <= "+values[1]);
			}else{
				changeSql.append(conditionField+" <= "+values[0]).append(" AND ").append(conditionField+" >= "+values[1]);
			}
			String newSql=StringUtil.keepInnerSpaceStr(ctx.getSql().substring(0,sql.indexOf("WHERE")+5));
			for (int i = 0; i < strs.length; i++) {
				if(i<index){
					newSql+=" "+strs[i]+" AND ";
				}else if(i==index){
					newSql+=" "+changeSql.toString();
				}else if(i>index+1){
					newSql+=" AND "+strs[i];
				}
			}
			ctx.setSql(newSql);
		}
	}

尋找路由呼叫:
       /**
	 * 多表路由
	 */
	public static RouteResultset tryRouteForTables(SchemaConfig schema, DruidShardingParseInfo ctx,
			RouteCalculateUnit routeUnit, RouteResultset rrs, boolean isSelect, LayerCachePool cachePool)
			throws SQLNonTransientException {
		
		List<String> tables = ctx.getTables();
		
		if(schema.isNoSharding()||(tables.size() >= 1&&isNoSharding(schema,tables.get(0)))) {
			if(Pattern.matches(".*_201\\d{5,5}", tables.get(0))){//支援分表, t_location_20170704這種表,刪除結尾的_20170704後再查詢路由
				TableConfig tc=schema.getTables().get( tables.get(0).substring(0,  tables.get(0).length()-9));
				return routeToSingleNode(rrs, tc.getDataNodes().get(0), ctx.getSql());
			}
			return routeToSingleNode(rrs, schema.getDataNode(), ctx.getSql());
		}
		
		// 處理BETWEEN AND 查詢
		SQLStatementParser parser = new MySqlStatementParser(ctx.getSql()); 
		SQLStatement statement = parser.parseStatement(); 
		if(statement instanceof SQLSelectStatement){
			// =======between and query to change SQL=======
			parseSQLToChangeBetweenSql(ctx);
			rrs.setStatement(ctx.getSql());
		}

		//只有一個表的
		if(tables.size() == 1) {
			return RouterUtil.tryRouteForOneTable(schema, ctx, routeUnit, tables.get(0), rrs, isSelect, cachePool);
		}

		Set<String> retNodesSet = new HashSet<String>();
		//每個表對應的路由對映
		Map<String,Set<String>> tablesRouteMap = new HashMap<String,Set<String>>();

		//分庫解析資訊不為空
		Map<String, Map<String, Set<ColumnRoutePair>>> tablesAndConditions = routeUnit.getTablesAndConditions();
		if(tablesAndConditions != null && tablesAndConditions.size() > 0) {
			//為分庫表找路由
			RouterUtil.findRouteWithcConditionsForTables(schema, rrs, tablesAndConditions, tablesRouteMap, ctx.getSql(), cachePool, isSelect);
			if(rrs.isFinishedRoute()) {
				return rrs;
			}
		}

		//為全域性表和單庫表找路由
		for(String tableName : tables) {
			TableConfig tableConfig = schema.getTables().get(tableName.toUpperCase());
			if(tableConfig==null && Pattern.matches(".*_201\\d{5,5}", tableName)){//支援分表, t_location_20170704這種表,支援結尾的_20170704後再查詢路由
				tableConfig=schema.getTables().get(tableName.substring(0, tableName.length()-9));
			}
			if(tableConfig == null) {
				String msg = "can't find table define in schema "+ tableName + " schema:" + schema.getName();
				LOGGER.warn(msg);
				throw new SQLNonTransientException(msg);
			}
			if(tableConfig.isGlobalTable()) {//全域性表
				if(tablesRouteMap.get(tableName) == null) {
					tablesRouteMap.put(tableName, new HashSet<String>());
				}
				tablesRouteMap.get(tableName).addAll(tableConfig.getDataNodes());
			} else if(tablesRouteMap.get(tableName) == null) { //餘下的表都是單庫表
				tablesRouteMap.put(tableName, new HashSet<String>());
				tablesRouteMap.get(tableName).addAll(tableConfig.getDataNodes());
			}
		}

		boolean isFirstAdd = true;
		for(Map.Entry<String, Set<String>> entry : tablesRouteMap.entrySet()) {
			if(entry.getValue() == null || entry.getValue().size() == 0) {
				throw new SQLNonTransientException("parent key can't find any valid datanode ");
			} else {
				if(isFirstAdd) {
					retNodesSet.addAll(entry.getValue());
					isFirstAdd = false;
				} else {
					retNodesSet.retainAll(entry.getValue());
					if(retNodesSet.size() == 0) {//兩個表的路由無交集
						String errMsg = "invalid route in sql, multi tables found but datanode has no intersection "
								+ " sql:" + ctx.getSql();
						LOGGER.warn(errMsg);
						throw new SQLNonTransientException(errMsg);
					}
				}
			}
		}

		if(retNodesSet != null && retNodesSet.size() > 0) {
			String tableName = tables.get(0);
			TableConfig tableConfig = schema.getTables().get(tableName.toUpperCase());
			if(tableConfig==null && Pattern.matches(".*_201\\d{5,5}", tableName)){//支援分表, t_location_20170704這種表,支援結尾的_20170704後再查詢路由
				tableConfig=schema.getTables().get(tableName.substring(0, tableName.length()-9));
			}
			if(tableConfig.isDistTable()){
				routeToDistTableNode(tableName,schema, rrs, ctx.getSql(), tablesAndConditions, cachePool, isSelect);
				return rrs;
			}
			
			if(retNodesSet.size() > 1 && isAllGlobalTable(ctx, schema)) {
				// mulit routes ,not cache route result
				if (isSelect) {
					rrs.setCacheAble(false);
					routeToSingleNode(rrs, retNodesSet.iterator().next(), ctx.getSql());
				}
				else {//delete 刪除全域性表的記錄
					routeToMultiNode(isSelect, rrs, retNodesSet, ctx.getSql(),true);
				}

			} else {
				routeToMultiNode(isSelect, rrs, retNodesSet, ctx.getSql());
			}

		}
		return rrs;

	}
關鍵呼叫:
		
		// 處理BETWEEN AND 查詢
		SQLStatementParser parser = new MySqlStatementParser(ctx.getSql()); 
		SQLStatement statement = parser.parseStatement(); 
		if(statement instanceof SQLSelectStatement){
			// =======between and query to change SQL=======
			parseSQLToChangeBetweenSql(ctx);
			rrs.setStatement(ctx.getSql());
		}

多個WHERE IN 查詢

支援多個IN查詢,主要操作io.mycat.backend.jdbc.mongodb.MongoSQLParser.java類:

	    
    /**
     * WHERE IN 查詢
     * @MethodName: parseWhereIn 
     * @Description: 
     * @param expr
     * @param query
     * @throws
     */
    private void parseWhereIn(SQLSelectStatement selectStmt,SQLExpr expr,DBObject query ){
        if(expr==null){
            return; // 沒有條件:no where conditions return this
        }
        String conditionStr=new String(expr.toString()).replaceAll(" ", "").toUpperCase().trim();
        if(conditionStr.contains("NOTIN(")){
            throw new IllegalArgumentException("Not support' WHERE $condition NOT IN ' sql statement");
        }else if(conditionStr.contains("IN(")){
            String sql=new String(selectStmt.getSelect().toString()).toUpperCase();
            String conditions=StringUtil.keepInnerSpaceStr(sql.substring(sql.lastIndexOf("WHERE")+5, sql.length())); 
            String manyIns[]=conditions.split("AND ");
            for (int a = 0; a < manyIns.length; a++) {
                if(manyIns[a].contains(" IN")){
                    String filedStr=StringUtil.keepInnerSpaceStr(manyIns[a].substring(0,manyIns[a].lastIndexOf("IN")));
                    String currentConditions=StringUtil.keepInnerSpaceStr(manyIns[a].substring(manyIns[a].lastIndexOf("(")+1, manyIns[a].lastIndexOf(")")));
                    String strs[]=filedStr.split(" ");
                    String field="";
                    for (int i = strs.length-1; i >=0 ; i++) {
                        if(!"".equals(strs[i].trim())){
                            field=strs[i].trim();
                            break;
                        }
                    }
                    String [] values=currentConditions.split(",");
                    BasicDBList blist=new BasicDBList();
                    for (int i = 0; i < values.length; i++) {
                        if(ValidateUtils.Number(values[i].trim())){
                            blist.add(Long.valueOf(values[i].trim()));
                        }else{
                            blist.add(values[i].trim());
                        }
                    }
                    BasicDBObject obj=new BasicDBObject();
                    obj.put("$in", blist);
                    query.put(field, obj);
                }
            }
        }
    }

支援NOT IN 查詢:

	
	/**
	 * WHERE IN 查詢
	 * @MethodName: parseWhereIn 
	 * @Description: 
	 * @param expr
	 * @param query
	 * @throws
	 */
	private void parseWhereIn(SQLSelectStatement selectStmt,SQLExpr expr,DBObject query ){
		if(expr==null){
			return; // 沒有條件:no where conditions return this
		}
		String conditionStr=new String(expr.toString()).replaceAll(" ", "").toUpperCase().trim();
		if(conditionStr.contains("IN(")||conditionStr.contains("NOTIN(")){
			String sql=new String(selectStmt.getSelect().toString()).toUpperCase();
			String conditions=StringUtil.keepInnerSpaceStr(sql.substring(sql.lastIndexOf("WHERE")+5, sql.length())); 
			String manyIns[]=conditions.split("AND");
			for (int a = 0; a < manyIns.length; a++) {
				String temp=new String(manyIns[a]).trim();
				if(temp.contains(" IN")&&!temp.contains("NOT IN")){
					String filedStr=StringUtil.keepInnerSpaceStr(manyIns[a].substring(0,manyIns[a].lastIndexOf(" IN")));
					String currentConditions=StringUtil.keepInnerSpaceStr(manyIns[a].substring(manyIns[a].lastIndexOf("(")+1, manyIns[a].lastIndexOf(")")));
					String strs[]=filedStr.split(" ");
					String field="";
					for (int i = strs.length-1; i >=0 ; i++) {
						if(!"".equals(strs[i].trim())){
							field=strs[i].trim();
							break;
						}
					}
					String [] values=currentConditions.split(",");
					BasicDBList blist=new BasicDBList();
					for (int i = 0; i < values.length; i++) {
						if(ValidateUtils.Number(values[i].trim())){
							blist.add(Long.valueOf(values[i].trim()));
						}else{
							blist.add(values[i].trim());
						}
					}
					BasicDBObject obj=new BasicDBObject();
					obj.put("$in", blist);
					query.put(field, obj);
				}else if(temp.contains(" IN")&&temp.contains("NOT IN")){
					String filedStr=StringUtil.keepInnerSpaceStr(manyIns[a].substring(0,manyIns[a].lastIndexOf("NOT IN")));
					String currentConditions=StringUtil.keepInnerSpaceStr(manyIns[a].substring(manyIns[a].lastIndexOf("(")+1, manyIns[a].lastIndexOf(")")));
					String strs[]=filedStr.split(" ");
					String field="";
					for (int i = strs.length-1; i >=0 ; i++) {
						if(!"".equals(strs[i].trim())){
							field=strs[i].trim();
							break;
						}
					}
					String [] values=currentConditions.split(",");
					BasicDBList blist=new BasicDBList();
					for (int i = 0; i < values.length; i++) {
						if(ValidateUtils.Number(values[i].trim())){
							blist.add(Long.valueOf(values[i].trim()));
						}else{
							blist.add(values[i].trim());
						}
					}
					BasicDBObject obj=new BasicDBObject();
					obj.put("$nin", blist);
					query.put(field, obj);
				}
			}
		}
	}
執行查詢呼叫:
       public MongoData query() throws MongoSQLException, SQLNonTransientException {
		if (!(statement instanceof SQLSelectStatement)) {
			// return null;
			throw new IllegalArgumentException("not a query sql statement");
		}
		MongoData mongo = new MongoData();
		DBCursor c = null;
		SQLSelectStatement selectStmt = (SQLSelectStatement) statement;
		SQLSelectQuery sqlSelectQuery = selectStmt.getSelect().getQuery();
		int icount = 0;
		if (sqlSelectQuery instanceof MySqlSelectQueryBlock) {
			MySqlSelectQueryBlock mysqlSelectQuery = (MySqlSelectQueryBlock) selectStmt.getSelect().getQuery();
			if (mysqlSelectQuery.getFrom() != null) {
				BasicDBObject fields = new BasicDBObject();
				// 顯示的欄位
				for (SQLSelectItem item : mysqlSelectQuery.getSelectList()) {
					// System.out.println(item.toString());
					if (!(item.getExpr() instanceof SQLAllColumnExpr)) {
						if (item.getExpr() instanceof SQLAggregateExpr) {
							SQLAggregateExpr expr = (SQLAggregateExpr) item.getExpr();
							if (expr.getMethodName().equals("COUNT")||expr.getMethodName().equals("SUM")) {
								icount = 1;
								mongo.setField(getExprFieldName(expr), Types.BIGINT);
							}
							fields.put(getExprFieldName(expr), Integer.valueOf(1));
						} else {
							fields.put(getFieldName(item), Integer.valueOf(1));
						}
					}

				}

				// 表名
				SQLTableSource table = mysqlSelectQuery.getFrom();
				DBCollection coll = this._db.getCollection(table.toString());
				mongo.setTable(table.toString());
				SQLExpr expr = mysqlSelectQuery.getWhere();
				DBObject query = parserWhere(expr);
				
				// parse where IN query 
				parseWhereIn(selectStmt, expr, query);
				// parse where IN query 
				
				SQLSelectGroupByClause groupby = mysqlSelectQuery.getGroupBy();
				BasicDBObject gbkey = new BasicDBObject();
				if (groupby != null) {
					for (SQLExpr gbexpr : groupby.getItems()) {
						if (gbexpr instanceof SQLIdentifierExpr) {
							String name = ((SQLIdentifierExpr) gbexpr).getName();
							gbkey.put(name, Integer.valueOf(1));
						}
					}
					icount = 2;
				}
				int limitoff = 0;
				int limitnum = 0;
				if (mysqlSelectQuery.getLimit() != null) {
					limitoff = getSQLExprToInt(mysqlSelectQuery.getLimit().getOffset());
					limitnum = getSQLExprToInt(mysqlSelectQuery.getLimit().getRowCount());
				}

				if (icount == 1) {
					/***********distinct***********/
					if(selectStmt.getSelect().toString().toLowerCase().contains("distinct")){
						DBCursor cursor=coll.find(query);
						Map<String,DBObject> distinctMap=new HashMap<String,DBObject>();
						for (DBObject dbObject : cursor) {
							String key=dbObject.toString().hashCode()+"";
							if(!distinctMap.containsKey(key)){
								distinctMap.put(key, dbObject);
							}
						}
						mongo.setCount(distinctMap.size());
					}else{
						mongo.setCount(coll.count(query));
					}
					/***********distinct***********/
					mongo.setAggrResult(true);
				} else if (icount == 2) {
					BasicDBObject initial = new BasicDBObject();
					initial.put("num", 0);
					String reduce = "function (obj, prev) { " + "  prev.num++}";
					mongo.setGrouyBy(coll.group(gbkey, query, initial, reduce));
				} else {
					if ((limitoff > 0) || (limitnum > 0)) {
						c = coll.find(query, fields).skip(limitoff).limit(limitnum);
					} else {
						c = coll.find(query, fields);
					}
					SQLOrderBy orderby = mysqlSelectQuery.getOrderBy();
					if (orderby != null) {
						BasicDBObject order = new BasicDBObject();
						for (int i = 0; i < orderby.getItems().size(); i++) {
							SQLSelectOrderByItem orderitem = orderby.getItems().get(i);
							order.put(orderitem.getExpr().toString(),
									Integer.valueOf(getSQLExprToAsc(orderitem.getType())));
						}
						c.sort(order);
						// System.out.println(order);
					}
				}
				mongo.setCursor(c);
			} else {
				mongo = query2();
			}

		}
		return mongo;
	}

核心呼叫:
				// 表名
				SQLTableSource table = mysqlSelectQuery.getFrom();
				DBCollection coll = this._db.getCollection(table.toString());
				mongo.setTable(table.toString());
				SQLExpr expr = mysqlSelectQuery.getWhere();
				DBObject query = parserWhere(expr);
				
				// parse where IN query 
				parseWhereIn(selectStmt, expr, query);
				// parse where IN query 

實現分段查詢原理

看完下面的內容就明白了:

db.getCollection('t_alarm_aggr_20170822').find({});

db.getCollection('t_alarm_aggr_20170822').find({ "F_START_TIME" : { "$gte" : "2017-08-21 00:00:00" , "$lte" : "2017-08-23 23:55:00"}});

db.getCollection('t_alarm_aggr_20170822').find({ "F_START_TIME" : { "$gte" : "2017-08-21 00:00:00" , "$lte" : "2017-08-23 23:55:00"} , "F_ID" : { "$in" : [5000000001063,5000000001064]}}).sort({"F_START_TIME":-1,"F_ALARM_ID":-1});



注:實際上只要滿足mongodb的shell命令就可以了。

測試驗證修改效果

BETWEEN AND:

mysql> SELECT F_ID, F_VEHICLE_ID, F_ALARMBAK, F_START_TIME, F_START_ID, F_END_TIME, F_STATUS, F_DSpeed, F_Speed, F_ALARM_ID, F_ENTERPRISE_ID FROM T_ALARM_AGGR WHERE F_START_TIME BETWEEN '2017-08-21 00:00:00' AND  '2017-08-23 23:55:00';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    108
Current database: cvnavidb

+---------------+------------------+------------+---------------------+---------------+---------------------+----------+----------+---------+------------+-----------------+
| F_ID          | F_VEHICLE_ID     | F_ALARMBAK | F_START_TIME        | F_START_ID    | F_END_TIME          | F_STATUS | F_DSpeed | F_Speed | F_ALARM_ID | F_ENTERPRISE_ID |
+---------------+------------------+------------+---------------------+---------------+---------------------+----------+----------+---------+------------+-----------------+
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-21 00:26:00 | 5000000468156 | 2017-08-21 00:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
| 5000000001064 | 4908520417546251 | NULL       | 2017-08-21 00:26:01 | 5000000468160 | 2017-08-21 00:26:01 |        0 | NULL     | NULL    |         49 | NULL            |
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-21 10:26:00 | 5000000468156 | 2017-08-21 10:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-22 00:26:00 | 5000000468156 | 2017-08-22 00:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
| 5000000001064 | 4908520417546251 | NULL       | 2017-08-22 00:26:01 | 5000000468160 | 2017-08-22 00:26:01 |        0 | NULL     | NULL    |         49 | NULL            |
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-22 10:26:00 | 5000000468156 | 2017-08-22 10:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-23 00:26:00 | 5000000468156 | 2017-08-23 00:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
| 5000000001064 | 4908520417546251 | NULL       | 2017-08-23 00:26:01 | 5000000830671 | 2017-08-23 00:26:01 |        0 | NULL     | NULL    |         49 | NULL            |
+---------------+------------------+------------+---------------------+---------------+---------------------+----------+----------+---------+------------+-----------------+
8 rows in set (0.25 sec)

mysql> 

WHERE IN:
mysql> SELECT F_ID, F_VEHICLE_ID, F_ALARMBAK, F_START_TIME, F_START_ID, F_END_TIME, F_STATUS, F_DSpeed, F_Speed, F_ALARM_ID, F_ENTERPRISE_ID FROM T_ALARM_AGGR WHERE F_START_TIME >= '2017-08-21 00:00:00' AND  F_START_TIME<='2017-08-23 23:55:00'  AND F_ID IN (5000000001064);
+---------------+------------------+------------+---------------------+---------------+---------------------+----------+----------+---------+------------+-----------------+
| F_ID          | F_VEHICLE_ID     | F_ALARMBAK | F_START_TIME        | F_START_ID    | F_END_TIME          | F_STATUS | F_DSpeed | F_Speed | F_ALARM_ID | F_ENTERPRISE_ID |
+---------------+------------------+------------+---------------------+---------------+---------------------+----------+----------+---------+------------+-----------------+
| 5000000001064 | 4908520417546251 | NULL       | 2017-08-22 00:26:01 | 5000000468160 | 2017-08-22 00:26:01 |        0 | NULL     | NULL    |         49 | NULL            |
| 5000000001064 | 4908520417546251 | NULL       | 2017-08-21 00:26:01 | 5000000468160 | 2017-08-21 00:26:01 |        0 | NULL     | NULL    |         49 | NULL            |
| 5000000001064 | 4908520417546251 | NULL       | 2017-08-23 00:26:01 | 5000000830671 | 2017-08-23 00:26:01 |        0 | NULL     | NULL    |         49 | NULL            |
+---------------+------------------+------------+---------------------+---------------+---------------------+----------+----------+---------+------------+-----------------+
3 rows in set (0.00 sec)

mysql> SELECT F_ID, F_VEHICLE_ID, F_ALARMBAK, F_START_TIME, F_START_ID, F_END_TIME, F_STATUS, F_DSpeed, F_Speed, F_ALARM_ID, F_ENTERPRISE_ID FROM T_ALARM_AGGR WHERE F_START_TIME >= '2017-08-21 00:00:00' AND  F_START_TIME<='2017-08-23 23:55:00'  AND F_ID IN (50000000010613,5000000001064);
+---------------+------------------+------------+---------------------+---------------+---------------------+----------+----------+---------+------------+-----------------+
| F_ID          | F_VEHICLE_ID     | F_ALARMBAK | F_START_TIME        | F_START_ID    | F_END_TIME          | F_STATUS | F_DSpeed | F_Speed | F_ALARM_ID | F_ENTERPRISE_ID |
+---------------+------------------+------------+---------------------+---------------+---------------------+----------+----------+---------+------------+-----------------+
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-23 00:26:00 | 5000000468156 | 2017-08-23 00:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
| 5000000001064 | 4908520417546251 | NULL       | 2017-08-23 00:26:01 | 5000000830671 | 2017-08-23 00:26:01 |        0 | NULL     | NULL    |         49 | NULL            |
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-22 00:26:00 | 5000000468156 | 2017-08-22 00:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
| 5000000001064 | 4908520417546251 | NULL       | 2017-08-22 00:26:01 | 5000000468160 | 2017-08-22 00:26:01 |        0 | NULL     | NULL    |         49 | NULL            |
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-21 00:26:00 | 5000000468156 | 2017-08-21 00:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-22 10:26:00 | 5000000468156 | 2017-08-22 10:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
| 5000000001064 | 4908520417546251 | NULL       | 2017-08-21 00:26:01 | 5000000468160 | 2017-08-21 00:26:01 |        0 | NULL     | NULL    |         49 | NULL            |
| 5000000001063 | 4908520417546251 | NULL       | 2017-08-21 10:26:00 | 5000000468156 | 2017-08-21 10:26:00 |        0 | NULL     | NULL    |         48 | NULL            |
+---------------+------------------+------------+---------------------+---------------+---------------------+----------+----------+---------+------------+-----------------+
8 rows in set (0.01 sec)

多個WHERE IN:


注:上面的測試注意驗證功能實現,實際開發中肯定有問題需要做更細緻的調整。

修改過原始碼後打包請備份jar包到其他路徑並刪除原來的jar在進行上傳! 下圖是因為沒有刪除導致修改程式包不起作用: