时间:2021-07-01 10:21:17 帮助过:20人阅读
1.例如表里某字段格式如下:数据1|||||数据2|||||数据3
2.现在想要把数据分割成$data[0],$data[1],$data[3],然后order by $data[3]
3.请问能实现吗?
4.完全小白,描述可能不规范,但意思应该说明白了。
能实现,如果在MySQL层面实现可能会导致数据库压力比较大.
可以考虑在PHP程序这边排好序,然后再根据ID序列从MySQL取数据.
- <code><!--?php
- header('Content-Type: text/plain; charset=utf-8');
- //$db = new mysqli('127.0.0.1','user','pass','dbname',3306);
- //$arr = $db--->query('SELECT id,field FROM table')->fetch_all(MYSQLI_ASSOC);
- //假设取出来的数据结构如下
- $arr = array(
- array('id' => 1, 'field' => '数据1|||||数据2|||||256'),
- array('id' => 2, 'field' => '数据1|||||数据2|||||128'),
- array('id' => 3, 'field' => '数据1|||||数据2|||||512'),
- );
- foreach($arr as $k => $v) {
- //把field字段的内容转成一个数组比如array('数据1','数据2','256'),方便后面排序
- $arr[$k]['field'] = explode('|||||', $v['field']);
- }
- //根据field字段里的第三个元素对数组进行排序
- uasort($arr, function($a, $b) {
- if($a['field'][2]===$b['field'][2]) return 0;
- //下面这句话的意思就是,如果前面的a大过后面的b,就返回1,返回1表示交换顺序,也就是小的数在前面,由小到大升序排列.
- else return ($a['field'][2] > $b['field'][2]) ? 1 : -1;
- });
- foreach($arr as $k => $v) {
- $ids[] = $v['id'];
- }
- $ids = implode(',', $ids); //ID序列为2,1,3
- //按照ID序列的顺序查询MySQL
- //SQL语句为 SELECT * FROM table WHERE id IN(2,1,3) ORDER BY FIELD(id,2,1,3)
- $sql = "SELECT * FROM table WHERE id IN($ids) ORDER BY FIELD(id,$ids)";
- //$ret = $db->query($sql)->fetch_all();</code>
如果数据量很大,可以考虑把PHP排好的ID序列缓存起来.
ORDER BY FIELD(id,$ids) 这个操作在数据量大时也会产生性能问题,
这时可以考虑根据实际情况对$ids进行切分,比如第一页0到19排序20条,第二页类推,这样小数据量的自定义排序对MySQL压力就小得多了.
这个和php没什么关系。你可以用mysql创建一个function,然后用function来排序:
- <code>CREATE FUNCTION SPLIT_STRING(str VARCHAR(255), delim VARCHAR(12), pos INT)
- RETURNS VARCHAR(255)
- RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),
- LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1),
- delim, '');</code>
- <code>SELECT * FROM test_table order by SPLIT_STRING(test_tablecol, '|||', 3);</code>
能实现,很麻烦,而且效率非常低,对于这种要求通常的解决办法是修改表结构。
从纯逻辑上来说,sql其实可以做很复杂的事情,但是你觉得如果一个查询需要跑好几分钟的话被家里人知道了会不会挨打?
建议查询出来之后用php排序,不要用mysql排序
mysql 的substring_index