主要介绍的是数据库的查询操作的原理,当然是非常浅显易懂的那种原理,更深层次的细节操作,调优操作还没有去做
想实现一个数据库查的操作,如果不考虑性能上的问题,并且不考虑词法、语法分析的问题。换言之,我们已经明白用户的语义了,并且只想实现这个功能,不考虑性能上的代价的话。那操作只分为三步:
1 . 连接操作:将多个表,两两做笛卡尔积
2 . 选择操作:将符合语义的行留下
3 . 投影操作:将每行中,需要输出的属性留下
当然,这里面我们忽略了很多的问题,如:
1 . 我们并没有考虑索引的存在
2 . 没有考虑性能上的问题,如果可以的话我们要尽可能的先选择,再做连接
以上便是,我模拟的过程,我们还是说一下,数据库正常查找的过程吧:
1.它会将用户输入的sql语句,进行语法、词法的分析
2.知道要干什么之后,会建立一棵二叉树,把所有要操作的内容,都放在叶子节点上面,把操作的函数放在双亲节点上面,然后会分析处理时间,然后调优,分析时间,最后会选择一种最为省时的时间的处理方式
下面看一下我处理选投连的方式吧:
/**
* 选择
*/
public static List<Integer> choose(List<String> keys, String[][] datas) {
List<Integer> result = new ArrayList<Integer>();
for (int i = 0; i < datas.length; i++) {
result.add(i);
}
for (int i = 0; i < keys.size(); i++) {
if (keys.get(i).contains("==")) {
//判断属性和某一个值相等
String lie = keys.get(i).split("==")[0];
int _lie = -1;
String key = keys.get(i).split("==")[1];
for (int ii = 0; ii < datas[0].length; ii++) {
System.out.println("lie:--->" + lie);
System.out.println("data:--->" + datas[0][ii]);
if (lie.equals(datas[0][ii])) {
_lie = ii;
System.out.println("lie:---> 发生相等");
}
}
for (int j = 0; j < datas.length; j++) {
if (datas[j][_lie].equals(key)) {
} else {
result.remove((Integer) j);
}
}
} else if (keys.get(i).contains(">")) {
String lie = keys.get(i).split(">")[0];
int _lie = -1;
String key = keys.get(i).split(">")[1];
for (int ii = 0; ii < datas[0].length; ii++) {
if (lie.equals(datas[0][ii])) {
_lie = ii;
}
}
for (int j = 0; j < datas.length; j++) {
try {
if (Integer.parseInt(datas[j][_lie]) > Integer.parseInt(key)) {
} else {
result.remove((Integer) j);
}
} catch (Exception e) {
result.remove((Integer) j);
}
}
} else if (keys.get(i).contains("=")) { //判断两个不同的属性的值相等
String key1 = keys.get(i).split("=")[0];
String key2 = keys.get(i).split("=")[1];
int _key1 = -1;
int _key2 = -1;
for (int ii = 0; ii < datas[0].length; ii++) {
if (key1.equals(datas[0][ii])) {
_key1 = ii;
}
if (key2.equals(datas[0][ii])) {
_key2 = ii;
}
}
for (int j = 0; j < datas.length; j++) {
if (datas[j][_key1].equals(datas[j][_key2])) {
} else {
result.remove((Integer) j);
}
}
}
}
return result;
}
/**
* 投影
*/
public static List<String> projection(List<Integer> result, List<String> information, String[][] datas) {
//result是要第几行
//information筛选的信息
//datas原始数据
List<String> resultList = new ArrayList<String>();//结果集合
List<Integer> keys = new ArrayList<Integer>();//最终要选择出来的属性的列号
String[] data1 = new String[datas[0].length];//属性信息,有几个,分别是什么
for (int i = 0; i < data1.length; i++) {
data1[i] = datas[0][i];//赋值
}
for (int i = 0; i < data1.length; i++) {
if (information.contains(data1[i])) {
keys.add(i);
}
}
String text = "";
for (int i = 0; i < datas.length; i++) {
if (result.contains((Integer) i)) {
for (int j = 0; j < datas[0].length; j++) {
if (keys.contains(j)) {
text = text + datas[i][j] + " ";
}
}
text = text.substring(0, text.length() - 1);
resultList.add(text);
text = "";
}
}
return resultList;
}
/**
* 连接
*/
public static String[][] connect(List<String> tables) {
String[] table1 = Util.readFileTo1(tables.get(0));//读取第一个表
String[] table2 = Util.readFileTo1(tables.get(1));//读取第二个表
String[] sum = new String[table1.length * table2.length];//建立新的表,做笛卡尔积
int count = 0;
for (int i = 0; i < table1.length; i++) {//做笛卡尔积的过程
for (int j = 0; j < table2.length; j++) {
sum[count] = table1[i] + " " + table2[j];
count++;
}
}
int length = sum[0].split(" ").length;//求出笛卡尔积后,一行的属性个数
String[][] result = new String[sum.length][length];
for (int i = 0; i < sum.length; i++) {
System.out.println("----> " + sum[i]);
}
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[0].length; j++) {
result[i][j] = sum[i].split(" ")[j];
}
}
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[0].length; j++) {
System.out.print(result[i][j] + "\\t");
}
System.out.println();
}
return result;
}
我们主要处理问题的三个函数就写好了,下面可以写一个主函数来测试一下:
在主函数中,我们需要,先调用连接函数,再调用选择函数,最后调用投影函数,这样就可以返回正确的答案啦,有空的时候我再把调用的函数,和效果图粘上来~