Прежде всего, убедитесь, что ваш столбец name_l
проиндексирован. Тогда вы можете просто использовать предложения ORDER BY
и LIMIT
следующим образом:
SELECT * FROM personnel ORDER BY name_l, id LIMIT 0, 1;
Просто увеличьте значение 0 в предложении LIMIT
, чтобы выбрать следующую запись в упорядоченном наборе. Поэтому используйте LIMIT 1, 1
для получения второй записи, LIMIT 2, 1
для третьей и т. Д.
Для создания индекса на name_l
вы можете использовать команду CREATE INDEX
:
CREATE INDEX ix_index_name ON personnel (name_l);
Контрольный пример:
CREATE TABLE personnel (
id int not null primary key,
name_l varchar(10),
name_f varchar(10)
);
CREATE INDEX ix_last_name_index ON personnel (name_l);
INSERT INTO personnel VALUES (1, 'Pacino', 'Al');
INSERT INTO personnel VALUES (2, 'Nicholson', 'Jack');
INSERT INTO personnel VALUES (3, 'De Niro', 'Robert');
INSERT INTO personnel VALUES (4, 'Newman', 'Paul');
INSERT INTO personnel VALUES (5, 'Duvall', 'Robert');
Результаты:
SELECT * FROM personnel ORDER BY name_l, id LIMIT 0, 1;
+----+---------+--------+
| id | name_l | name_f |
+----+---------+--------+
| 3 | De Niro | Robert |
+----+---------+--------+
1 row in set (0.00 sec)
SELECT * FROM personnel ORDER BY name_l, id LIMIT 1, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 5 | Duvall | Robert |
+----+--------+--------+
1 row in set (0.00 sec)
SELECT * FROM personnel ORDER BY name_l, id LIMIT 2, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 4 | Newman | Paul |
+----+--------+--------+
1 row in set (0.00 sec)
1-е ОБНОВЛЕНИЕ: (в дополнение к комментариям ниже)
Приведенный выше пример подходит, главным образом, если вы начинаете с отображения первой записи, а затем последовательно переходите к следующей, а может быть, снова следующей, а возможно, еще одной назад и т. Д. Вы также можете легко перемещать x шагов вперед и x шагов назад , но это не требуется.
Однако, если вы начнете со случайной записи, вам будет сложнее адаптировать приведенный выше запрос для получения следующей и предыдущей записей.
Если это так, то вы можете просто сохранить счетчик индекса того, где вы находитесь в данный момент. Вы начинаете с $index = 0
и отображаете первую запись с помощью ... LIMIT $index, 1
. Затем вы отображаете следующее, увеличивая $index
на 1, и отображаете предыдущее, уменьшая $index
на 1.
Если, с другой стороны, вы будете обрабатывать список персонала, а затем пользователь щелкнет одну запись (случайным образом), вы также можете выполнить эту работу с некоторой помощью со стороны приложений (php). Допустим, вы предоставляете пользователю следующий упорядоченный список:
+----+-----------+--------+
| id | name_l | name_f |
+----+-----------+--------+ // [Hidden info]
| 3 | De Niro | Robert | // Row 0
| 5 | Duvall | Robert | // Row 1
| 4 | Newman | Paul | // Row 2
| 2 | Nicholson | Jack | // Row 3
| 1 | Pacino | Al | // Row 4
+----+-----------+--------+
Теперь, если пользователь щелкнет по Newman Paul, вам нужно будет передать параметр row=2
на страницу, где будут отображаться сведения об этом сотруднике. Страница, на которой отображаются сведения о сотруднике, теперь знает, что Ньюман Пол находится в 3-й строке (row=2
). Поэтому, чтобы получить предыдущую и следующую записи, вы просто изменили бы x
в LIMIT x, 1
на row - 1
для предыдущей записи и row + 1
для следующей:
-- Previous
SELECT * FROM personnel ORDER BY name_l, id LIMIT 1, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 5 | Duvall | Robert |
+----+--------+--------+
1 row in set (0.00 sec)
-- Next
SELECT * FROM personnel ORDER BY name_l, id LIMIT 3, 1;
+----+-----------+--------+
| id | name_l | name_f |
+----+-----------+--------+
| 2 | Nicholson | Jack |
+----+-----------+--------+
1 row in set (0.00 sec)
2-е ОБНОВЛЕНИЕ:
Вы можете использовать следующий специфичный для MySQL запрос, чтобы получить номер записи в упорядоченном списке любого случайного сотрудника, который затем можно использовать для получения предыдущей и следующей записей. Однако обратите внимание, что это не очень эффективно и может привести к снижению производительности, если у вас есть тысячи записей.
Допустим, вы работаете с Николсоном Джеком.
Вы могли бы сделать следующий запрос:
SELECT p.id, p.name_l, p.name_f, o.record_number
FROM personnel p
JOIN (
SELECT id,
@row := @row + 1 AS record_number
FROM personnel
JOIN (SELECT @row := -1) r
ORDER BY name_l, id
) o ON (o.id = p.id)
WHERE p.name_l = 'Nicholson' AND p.name_f = 'Jack';
Что возвращает это:
+----+-----------+--------+---------------+
| id | name_l | name_f | record_number |
+----+-----------+--------+---------------+
| 2 | Nicholson | Jack | 3 |
+----+-----------+--------+---------------+
1 row in set (0.00 sec)
Обратите внимание, что в предложении WHERE
вы могли бы использовать p.id = 2
, если идентификатор известен, вместо p.name_l = 'Nicholson' AND p.name_f = 'Jack'
.
Теперь мы можем использовать поле record_number
, в данном случае 3
, чтобы получить предыдущую и следующую записи, просто используя исходный запрос в верхней части этого ответа и заменив LIMIT 2, 1
на предыдущий и LIMIT 4, 1
для следующего. Вот и вы:
Предыдущий Николсон Джек:
SELECT * FROM personnel ORDER BY name_l, id LIMIT 2, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 4 | Newman | Paul |
+----+--------+--------+
1 row in set (0.00 sec)
Следующее от Николсона Джека:
SELECT * FROM personnel ORDER BY name_l, id LIMIT 4, 1;
+----+--------+--------+
| id | name_l | name_f |
+----+--------+--------+
| 1 | Pacino | Al |
+----+--------+--------+
1 row in set (0.00 sec)