数据库中的分类搜索

        我们在学习数据库的过程中,可以很清楚地了解到,如果要搜索我们需要的数据,就要在WHERE之后添加我们的条件,当然,搜索可以用LIMIT要求获取某个范围的数据,也可以用ORDER  BY来对获取的数据进行排序输出,也可以用MAX(  )或者MIN(  )等函数获取其中的最值,但是如果要分类呢?要怎么写sql语句才能符合我们想获得的数据呢?

        下面举一个简单的例子:

        我这里有一个回复的表格,用来记录所有对某个主题的回复,我先创建这个表格:

CREATE TABLE IF NOT EXISTS reply(
        reply_id INT NOT NULL ,
        subject_id INT NOT NULL ,
        replyer_id INT NOT NULL ,
        reply_content VARCHAR(50) DEFAULT "" ,
        reply_time DATETIME NOT NULL ,
        PRIMARY KEY(reply_id)
      );

        这是一个比较简单的reply(回复)的表格,用来记录其他人对某个主题的回复记录,replt_id是主键,subject_id是回复的主题id,replyer_id是回复人的账号id,而reply_content就是回复的内容,reply_time是回复的时间。

        好了,大概了解了这个表是干什么的了。

        那么现在,如果我想做一件事,展示一下所有的回复内容,那么我应该如何做呢?如果单纯获取所有回复很简单,就一句话:

SELECT * FROM reply;

        但是,我想获取某个主题(假设这个主题id为888)的所有回复内容呢?也是一句话:

SELECT * FROM reply WHERE reply.subject_id=888;

        这也只是在后面加个WHERE条件而已,那如果我需要获取某个主题(假设这个主题id为888)的最后回复时间呢?可以这样写:

SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id=888;

        可以用最大值代表最后的回复时间。那又如果我想获取好几个主题(假设这几个主题id为111,333,888)的最后回复时间呢?

        可能瞬间你会想到用IN,这样:

SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id IN (111,333,888);

        但是很显然,这是错的,因为你只是在三个主题(111,333,888)下的所有情况搜索出最后的回复时间,而没有每一条主题的回复时间,所以结果最多只有一条。

        当然了,你可以用UNION方法达到效果:

SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id=111
UNION
SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id=333
UNION
SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id=888;

        但是我只给你一个数组呢,要你用IN方法写出来呢?

        那就要从最根本查找语句的逻辑出发了,因为我们是查找某些主题下的最后回复时间,那么我们从整个表中查找的话,那就只需要给我所有的最后回复时间啊,我先不管最后回复时间是怎样来的,我也可以先写出这样的语句:

SELECT reply_time, reply_id FROM reply 
WHERE ……;

        好了,这个时候我们就要考虑怎样获取到所有的主题,这里就要借用一个技巧,借用一下别名,因为我们需要找出所有的主题,那么如何找,那就需要用两个表来确认subject_id相等的地方,那就可以找出所有同一主题的数据,再从中提取最大值,那就可以了:

SELECT reply_time, reply_id FROM reply AS a
WHERE 
(SELECT MAX(b.reply_time) FROM reply AS b 
WHERE
a.subject_id=b.subject
);

        最后,再加上需要查找的subject_id就可以了:

SELECT reply_time, reply_id FROM reply AS a
WHERE 
(SELECT MAX(b.reply_time) FROM reply AS b 
WHERE
a.subject_id=b.subject AND b.subject IN (111,333,888)
);

        上面就是一个简单的分类搜索语句,但是实际应用中,有很多远远复杂的要求,所以对sql语句的掌握也是非常重要的。

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

数据库中的事务

        在数据库中,事务就是一个执行操作的工作单元。说得简单点,就是一个包含多个数据库操作的任务。例如,你先查这个表数据,然后再删那个表数据,再去创建一个新数据,这样的一系列的操作组成一个事务来管理。

        事务有四个标准属性:ACID。就是:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

        其实我不太喜欢太多的名词,在我看来,事务就是可以让你这些操作均成功完成,若其中一个操作发生错误,则全部回滚到最初状态。

        关于这个事务处理,基于它的特点,所以有一个很重要的特征,就是事务中的每个sql语句是不会立即提交(COMMIT)的,只会当你需要提交的时候,或者结束事务的时候才统一提交(COMMIT)的。

        举一个简单的例子,我在使用SQLite(SQLite是一个轻量级的数据库,无需建立数据库连接,只需引入数据文件即可)的时候遇到了一个问题,我在一个服务器运行之前,需要检测一下数据库中的区域信息,也就是所有的省市区的常规信息的时候,执行一个sql文件(这个区域信息可以参考这个文件:区域信息)中的语句,发觉很慢,超级慢,打开SQLite Expert Pro(一款数据库可视化工具)观察,等了很久很久,然后点击一下,就崩了,发觉这样执行完全不行啊。然后用可视化工具直接复制语句进去执行,等了很久出来了部分数据,然后报错了。

        最后就找到需要用事务处理这种办法,因为sql语句中有好几千条数据,如果每读取一条执行语句都要commit一下,那么这段语句就要commit几千次了,对数据库的负担是很大的,虽然这种做法在MySQL中可以很快就完成了,但是在SQLite这种轻量级的数据库中却不是一件容易的事情,所以我在所有语句的前面加入语句:

BEGIN TRANSACTION;

        然后在所有语句最后加入语句:

END TRANSACTION;   # 或者COMMIT;

        这样就将整段语句作为事务来处理了,然后执行的时候就一瞬间就插入到数据库中了,所以数据库中的事务是非常有用的。

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

MySQL基本语法

        MySQL作为最流行的关系型数据库之一,当然有它自身的代表性,语句简练清晰,当然了,我们写编程很多实际用到的都是orm工具,例如node中的sequelize,都对数据库做了很好的封装,屏蔽了对数据库的直接语句操作,不过,原生操作语句还是要掌握好的。

        特别一些语句多起来的时候,特别要注重优化问题,看过一下数据库工程师抽丝剥茧,将一大串语句优化到操作时间减少大半时间的。

        其实关系型数据库的SQL语句都是大同小异的,这里就用MySQL的语句作为举例。这里只是单纯说一说一些基础的基本语法,不会全部遍及,当作笔记也可。

        MySQL存储的数据类型基本分为数字、字符串、时间等三类,MySQL5.7开始也支持JSON格式的存储,这方面不详说。

        数字又分为整形、浮点型,其中又分为不同长度的数据TINYINT、SMALLINT、FLOAT、DOUBLE等等,字符串定长、变长的字符串、长短文本及其二进制数据,CHAR、VARCHAR、TEXT等都是常见的类型,而时间基本分为时间值和时间戳,时间值就是一个点,而时间戳(TIMESTAMP)就是1970-01-01 00:00:00起到现在的总秒数,如果是32位操作系统的计算机,能表示的最大值为2147483647,68年,所以到了2038年这个操作系统的计算机会发生数据溢出,时间回去到1901年。

        其实对于学强类型语言的来说,例如JAVA、C++等的,对于这些数据类型来说,都不会陌生,耳熟能详的东西。

        创建表格就不多说了,一个例子很明白套路:

CREATE TABLE IF NOT EXISTS `ershing`(
   `ershing_id` INT UNSIGNED AUTO_INCREMENT,
   `ershing_name` VARCHAR(20) NOT NULL,
   `ershing_introduction` VARCHAR(160) NOT NULL,
   `create_time` DATE,
   PRIMARY KEY ( `ershing_id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

        其实就是表格名称、字段和字段类型要求及一些主键或非空等的配置而已。

        好了,其实重要的还是对数据库操作,而数据库操作,无非就是增、删、改、查这几个操作,但是不要小看这几个操作,如果是多条件多表格组合的语句,足以搞晕,废话少说,直接来语句。

增:

INSERT INTO ershing
(ershing_name, ershing_introduction, create_time)
VALUES
("MySQL", "基本语法", NOW());

        就是用关键字INSERT INTO来对某个表格的某个字段插入某个值。

删:

DELETE FROM ershing WHERE ershing_id=7;

        就是用关键字DELETE FROM来对某个表格的某个位置的数据进行删除。

改:

UPDATE ershing SET ershing_name='SQLite' WHERE ershing_id=2;

        就是用UPDATE SET关键字对某个表格的某个字段内容进行更新操作。

查:

SELECT 
ershing_name, ershing_introduction, create_time
FROM ershing
WHERE ershing_id=3;

        就是用关键字SELECT FROM来选择在某些表中某地方的某些需要的字段。

        上面这些就是最基本的一些操作,至于其他的一些常用语句语法还有:

        Like:结合%来模糊搜索关键字,例如:WHERE  ershing_name  LiKE  ‘%SQL%’

        IN:多个条件,例如:SELECT  *  FROM  ershing WHERE ershing_id  IN (3,1,5)

        UNION:多个结果集合,例如:SELECT …FROM  …UNION  SELECT …FROM…

        LIMIT:辅助分页,例如:SELECT * FROM   ershing  LIMIT 5,10

        ORDER BY:排序,例如:SELECT  *  FROM  ershing  ORDER  BY  ‘create_time’  DESC;

        GROUP BY:分组,例如SELECT ershing_name, COUNT(*) FROM ershing GROUP BY ershing_name;

        多表连接:INNER JOIN(两表交集)、LEFT JOIN(左表基础上加两表交集的右表其余字段)、RIGHT JOIN(右表基础上加左表交集的其余字段)

        上面这些,相信足以应付85%以上的数据库操作要求了,关键还是具体问题具体分析,用好SQL语句还是很有必要的。

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

数据库

        什么是数据库,百度解释就是:数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。见名思意,就是存库数据的仓库,由于数据的重要性日益突出,特别数据以几何级数量增长的今天,所以学好数据库技术显得尤其重要。

        数据库通常分为层次式数据库、网络式数据库和关系式数据库三种。而不同的数据库是按不同的数据结构来联系和组织的。而在当今的互联网中,最常见的数据库模型主要是两种,即关系型数据库和非关系型数据库。

        先说说关系型数据库。

        关系型数据库模型是把复杂的数据结构归结为简单的二元关系(即二维表格形式)。在关系型数据库中,对数据的操作几乎全部建立在一个或多个关系表格上,通过对这些关联的表格分类、合并、连接或选取等运算来实现数据库的管理。

        其实可以这样理解,例如有一个数据“我是张三,今年20岁,身高178cm,体重75kg”,那么我们就可以创建一个人员信息的表格,横向有姓名、年龄、身高、体重等字段,纵向就可以保存上述这一条信息。就像我们平时用的excel那样,一个有横竖的表格来存储我们这样的数据,可以通过不同表格的关联来实现增删查改。

        常用的关系型数据库有:Oracle、MySQL、MariaDB、SqlServer、Access等。

        那什么是非关系型数据库呢?

        听说过NoSQL吧,就是Not only SQL的意思,泛指非关系型数据库。这里贴个百度百科的地址:https://baike.baidu.com/item/NoSQL/8828247?fr=aladdin。里面有详细的介绍,这里复制粘贴它的四大分类表格介绍:

分类 Examples举例 典型应用场景 数据模型 优点 缺点
键值(key-value) Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。 Key 指向 Value 的键值对,通常用hash table来实现 查找速度快 数据无结构化,通常只被当作字符串或者二进制数据
列存储数据库 Cassandra, HBase, Riak 分布式的文件系统 以列簇式存储,将同一列数据存在一起 查找速度快,可扩展性强,更容易进行分布式扩展 功能相对局限
文档型数据库 CouchDB, MongoDb Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) Key-Value对应的键值对,Value为结构化数据 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 查询性能不高,而且缺乏统一的查询语法。
图形(Graph)数据库 Neo4J, InfoGrid, Infinite Graph 社交网络,推荐系统等。专注于构建关系图谱 图结构 利用图结构相关算法。比如最短路径寻址,N度关系查找等 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。

        现在NoSQL仿佛是一种风向的趋势,未来有很大的发展空间。当然,关系型数据库还是大型公司的主流,未来的两者发展关系不得而知,不过关系型数据库是不会消亡的。

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。