如何在 CodeIgniter 3 中获取下一个和上一个 ID?
How to get next and previous id on CodeIgniter3?
我有以下数据库。
+----+------+
| id | name |
+----+------+
| 1 | aaaa |
| 2 | bbbb |
| 4 | dddd |
| 7 | gggg |
+----+------+
如您所见,身份证少了一颗牙。
因此您无法通过简单地在当前 ID 上加或减 1 来获得有效的上一个或下一个 ID
在SQL中,为了得到一个有效的来回ID,我会这样写。
SELECT
(SELECT id FROM topics WHERE id < tmp.id ORDER BY id DESC LIMIT 1) AS prev_id,
(SELECT id FROM topics WHERE id > tmp.id ORDER BY id ASC LIMIT 1) AS next_id
FROM
topics AS tmp
WHERE
id = 1
;
+---------+---------+
| prev_id | next_id |
+---------+---------+
| NULL | 2 |
+---------+---------+
id = 2
+---------+---------+
| prev_id | next_id |
+---------+---------+
| 1 | 4 |
+---------+---------+
id = 4
+---------+---------+
| prev_id | next_id |
+---------+---------+
| 2 | 7 |
+---------+---------+
id = 7
+---------+---------+
| prev_id | next_id |
+---------+---------+
| 4 | NULL |
+---------+---------+
id = 999
empty set
我想通过CodeIgniter3风格的方式获取这种记录检索。
我怎样才能把它写成 codeigniter3 活动记录?
@sajushko
感谢您的回复。
我已确认它按我的预期工作。
但是我想知道的是如何在CodeIgniter3的ActiveRecord中写,而不是SQL语句
具体是这样的
public function getBothIds($id)
{
$tableName = "topics";
$columnName = "id";
$asColumnNamePrev = "prev_" . $columnName;
$asColumnNameNext = "next_" . $columnName;
$query = $this->db
->select_min($columnName, $asColumnNamePrev) // how to write where inside of select_min?
->select_max($columnName, $asColumnNameNext) // how to write where inside of select_max?
->where($columnName, $id)
->get($tableName)
->row();
return $query;
}
由于将 SQL 语句直接写入业务逻辑是 SQL 注入的原因,我们希望使用包装函数来编写它们。
这可能会如您所愿
CREATE TABLE `topics` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(250),
PRIMARY KEY (`id`)
);
INSERT INTO `topics` VALUES (1, 'aaaa');
INSERT INTO `topics` VALUES (2, 'bbbb');
INSERT INTO `topics` VALUES (4, 'dddd');
INSERT INTO `topics` VALUES (7, 'gggg');
SELECT
(SELECT MAX(`id`) FROM `topics` WHERE id < `tmpTopics`.`id`) AS `prev_id`,
(SELECT MIN(`id`) FROM `topics` WHERE id > `tmpTopics`.`id`) AS `next_id`
FROM
`topics` AS `tmpTopics`
WHERE
`id` = 1;
这里是SQLFiddle例子http://sqlfiddle.com/#!9/83968c/8
好吧,我想出了如何将它写成 codeigniter3 风格,就像这样。
请让我知道任何其他比我更酷的代码。
/**
* Get Prev And Next Id
*
* @param integer|string $id e.g. 1
* @return stdClass|null
*/
public function getNeighborIds($id)
{
/**
* SELECT
* (SELECT MAX(`id`) FROM `topics` WHERE `id` < `tmp`.`id`) AS `prev_id`,
* (SELECT MIN(`id`) FROM `topics` WHERE `id` > `tmp`.`id`) AS `next_id`
* FROM
* `topics` AS `tmp`
* WHERE
* `id` = 10;
*/
$tableName = $this->tableName;
$columnName = $this->primaryKey;
$asColumnNamePrev = "prev_" . $columnName;
$asColumnNameNext = "next_" . $columnName;
$queryMin = '(SELECT MAX(' . $columnName . ') FROM ' . $tableName . ' WHERE ' . $columnName . ' < ' . 'tmp.' . $columnName . ') AS ' . $asColumnNamePrev;
$queryMax = '(SELECT MIN(' . $columnName . ') FROM ' . $tableName . ' WHERE ' . $columnName . ' > ' . 'tmp.' . $columnName . ') AS ' . $asColumnNameNext;
$query = $this->db
->select($queryMin)
->select($queryMax)
->where($columnName, $id)
->get($tableName . ' AS tmp')
->row();
return $query; // e.g. $query->prev_id "8" $query->next_id "11"
}
我有以下数据库。
+----+------+
| id | name |
+----+------+
| 1 | aaaa |
| 2 | bbbb |
| 4 | dddd |
| 7 | gggg |
+----+------+
如您所见,身份证少了一颗牙。
因此您无法通过简单地在当前 ID 上加或减 1 来获得有效的上一个或下一个 ID
在SQL中,为了得到一个有效的来回ID,我会这样写。
SELECT
(SELECT id FROM topics WHERE id < tmp.id ORDER BY id DESC LIMIT 1) AS prev_id,
(SELECT id FROM topics WHERE id > tmp.id ORDER BY id ASC LIMIT 1) AS next_id
FROM
topics AS tmp
WHERE
id = 1
;
+---------+---------+
| prev_id | next_id |
+---------+---------+
| NULL | 2 |
+---------+---------+
id = 2
+---------+---------+
| prev_id | next_id |
+---------+---------+
| 1 | 4 |
+---------+---------+
id = 4
+---------+---------+
| prev_id | next_id |
+---------+---------+
| 2 | 7 |
+---------+---------+
id = 7
+---------+---------+
| prev_id | next_id |
+---------+---------+
| 4 | NULL |
+---------+---------+
id = 999
empty set
我想通过CodeIgniter3风格的方式获取这种记录检索。 我怎样才能把它写成 codeigniter3 活动记录?
@sajushko
感谢您的回复。 我已确认它按我的预期工作。
但是我想知道的是如何在CodeIgniter3的ActiveRecord中写,而不是SQL语句
具体是这样的
public function getBothIds($id)
{
$tableName = "topics";
$columnName = "id";
$asColumnNamePrev = "prev_" . $columnName;
$asColumnNameNext = "next_" . $columnName;
$query = $this->db
->select_min($columnName, $asColumnNamePrev) // how to write where inside of select_min?
->select_max($columnName, $asColumnNameNext) // how to write where inside of select_max?
->where($columnName, $id)
->get($tableName)
->row();
return $query;
}
由于将 SQL 语句直接写入业务逻辑是 SQL 注入的原因,我们希望使用包装函数来编写它们。
这可能会如您所愿
CREATE TABLE `topics` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(250),
PRIMARY KEY (`id`)
);
INSERT INTO `topics` VALUES (1, 'aaaa');
INSERT INTO `topics` VALUES (2, 'bbbb');
INSERT INTO `topics` VALUES (4, 'dddd');
INSERT INTO `topics` VALUES (7, 'gggg');
SELECT
(SELECT MAX(`id`) FROM `topics` WHERE id < `tmpTopics`.`id`) AS `prev_id`,
(SELECT MIN(`id`) FROM `topics` WHERE id > `tmpTopics`.`id`) AS `next_id`
FROM
`topics` AS `tmpTopics`
WHERE
`id` = 1;
这里是SQLFiddle例子http://sqlfiddle.com/#!9/83968c/8
好吧,我想出了如何将它写成 codeigniter3 风格,就像这样。
请让我知道任何其他比我更酷的代码。
/**
* Get Prev And Next Id
*
* @param integer|string $id e.g. 1
* @return stdClass|null
*/
public function getNeighborIds($id)
{
/**
* SELECT
* (SELECT MAX(`id`) FROM `topics` WHERE `id` < `tmp`.`id`) AS `prev_id`,
* (SELECT MIN(`id`) FROM `topics` WHERE `id` > `tmp`.`id`) AS `next_id`
* FROM
* `topics` AS `tmp`
* WHERE
* `id` = 10;
*/
$tableName = $this->tableName;
$columnName = $this->primaryKey;
$asColumnNamePrev = "prev_" . $columnName;
$asColumnNameNext = "next_" . $columnName;
$queryMin = '(SELECT MAX(' . $columnName . ') FROM ' . $tableName . ' WHERE ' . $columnName . ' < ' . 'tmp.' . $columnName . ') AS ' . $asColumnNamePrev;
$queryMax = '(SELECT MIN(' . $columnName . ') FROM ' . $tableName . ' WHERE ' . $columnName . ' > ' . 'tmp.' . $columnName . ') AS ' . $asColumnNameNext;
$query = $this->db
->select($queryMin)
->select($queryMax)
->where($columnName, $id)
->get($tableName . ' AS tmp')
->row();
return $query; // e.g. $query->prev_id "8" $query->next_id "11"
}