MySQL in 查询,并经过 FIELD 函数按照查询条件顺序返回结果

从示例讲起

咱们都很是习惯经过 MySQL 的 IN 函数来查询特定集合的数据,好比为了在 books 表中找出李雷、韩梅梅和安华写的书,咱们能够有以下的 SQL:html

SELECT * FROM books WHERE `books`.`author` IN ('李雷','韩梅梅','安华');

注意: 能够经过 SQL Fiddle 查看以上示例。mysql

数据库返回以下结果:sql

author title
安华 暴走漫画
李雷 蓝色生死恋
韩梅梅 冰与火之歌
韩梅梅 天国的阶梯
李雷 这个杀手不太冷
韩梅梅 阿甘正传

虽然这样确实可以返回全部李雷、韩梅梅和安华写过的书,可是返回的数据的排序方式是默认按照数据在数据库中的存储顺序,假如咱们须要的返回结果是同时按照 IN 查询条件里边的参数顺序来排序呢?这个时候咱们就须要利用到 MySQL FIELD 这个函数了,FIELD 函数原本是 MySQL 提供用来查询某一个字符串在给定字符串元组中的索引位置的,好比这个官方例子:数据库

SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo'); # -> 2

若是将其应用在 ORDER BY 排序条件中,就能够根据指定字段的值在给定参数列表中的索引数值,进而将查询结果按照参数列表排序了:数组

SELECT * FROM books WHERE `books`.`author` IN ('李雷','韩梅梅','安华') ORDER BY FIELD(author, '李雷','韩梅梅','安华');

注意: 能够经过SQL Fiddle查看以上示例。服务器

这一次,返回的结果则是:函数

author title
李雷 蓝色生死恋
李雷 这个杀手不太冷
韩梅梅 冰与火之歌
韩梅梅 天国的阶梯
韩梅梅 阿甘正传
安华 暴走漫画

能够发现,这一次,咱们获得的结果就是按照条件参数列表 '李雷','韩梅梅','安华' 进行排序后获得了。性能

应用层面的思考

1. 兼容性

本文提到的 FIELD 函数,毕竟只是 MySQL 数据库内置提供的一种函数,除非你很是明确你的项目就是只用 MySQL 数据库,不然,你的 SQL 代码在将来迁移到其余数据库的过程当中就会遇到语法兼容性问题(只是 PostgreSQL 数据库不支持 FIELD)。code

2. 性能问题

咱们都知道,数据库在进行 ORDER BY 排序的时候,除非它是按照某个已经存在索引的键的值进行排序,不然数据库则须要经过计算 ORDER BY 中表达式的值而且按照查询结果创建新的临时表,这个过程会带来额外的时间开销跟内存开销,对数据库自己就是一种性能负担。这样的方式在单一数据库多个数据库客户端链接的时候,可能对数据库形成太大负担。htm

3. 与应用层代码的结合

尽管使用 FIELD 函数可能带来兼容性以及性能方面的隐患,可是 FIELD 的使用并不是全是有损之处。

好比在与 Ruby 的 active_record 结合时,这种经过数据库直接完成排序等 SQL 语句能够方便咱们构建 ActiveRecord::Relation 对象,由于咱们再也不须要先将查询结果集从内存中转为数组排序,再进行二次查询,能够帮助咱们减小 N+1 查询问题,后者也是常见的影响数据库服务器性能的现象之一。除此以外,这样的写法也能够有效地帮助咱们简化代码,保持代码简洁。

可是在不须要对数据进行二次查询或者查询数据量太大的状况下,我反而建议能够经过 Ruby 的 Array#sort_by 方法对数据进行排序,这样的话,排序的任务就转移给了客户端代码,排序任务的压力就天然分散,减轻了服务器端的压力。

总结

  1. FIELD 函数结合 ORDER BY 能够帮助咱们将查询结果集按照参数列表顺序返回;

  2. FIELD 函数结合 ORDER BY 的方式能够帮助咱们在数据库层面完成排序,简化了业务代码逻辑;

  3. FIELD 函数结合 ORDER BY 可能带来 SQL 兼容性以及性能方面的问题;

  4. 在确认项目数据库不大可能为 MySQL
    以外的数据库的前提下,查询数据量少或者须要保持业务代码简洁的场景下,我建议能够采用 FIELD 函数排序;而在数据量庞大的状况下,或者不大可能出现大量 N+1 查询的状况下,我建议能够采用先在数据库中查询数据集(只查询 IN 条件,不排序)再到内存中经过业务代码排序(好比 Ruby 的 Array#sort_by)的方式。

相关文章
相关标签/搜索