Xpoint
   [напомнить пароль]

Как выбрать предыдущую запись?

Метки: [без меток]
2008-02-24 08:56:35 [обр] x28[досье]

Ковыряние в доке и поиск в инете ничего не дали. Такой трабл:
Например, есть записи в таблице:

1 Иванов
2 Петров
5 Сидоров
6 Бандерас
7 Пангемон

Нужно выбрать запись, которая находится перед известной, например мне известна фамилия Сидоров, запрос должен вернуть Петров. Если указать первую запись, должна выбраться последняя (для "Иванов" это "Пангемон").

Можно ли это сделать только SQL запросами, или придётся считывать всю базу и php скриптом выбирать нужные записи?

спустя 5 часов [обр] Алексей Севрюков(7/1292)[досье]
x28[досье] можно сделать только SQL запросами. Вам поможет ORDER BY id DESC + LIMIT 1, ну и естественно нужно знать id записи, чтобы выбрать "предыдущую" запись. Вариант с первой записью — исключение, его придется прорабатывать отдельно, но это тоже можно сделать только SQL запросами.
спустя 40 минут [обр] Дмитрий Попов(17/509)[досье]
Ну в общем-то да, только помимо order и limit, еще where забыл =)
Т.е. если знать номер сидорова, то where no<номер_сидорова order by no DESC limit 1, если не знать - то он элементарно получается одним дополнительным запросом.
А по случаю первой записи - тут без клиента сложно, но клиент должен просто обработать ситуацию, когда первый запрос вернул null, и в таком случае выполнить этот же запрос но без where
спустя 5 минут [обр] Алексей Севрюков(7/1292)[досье]
Дмитрий Попов[досье] where оставил на домашнее задание.
спустя 17 часов [обр] x28[досье]

Эх, я немного неудачный пример с идентификаторами привёл - идентификаторы могут не быть в возрастающей последовательности. Для чистоты эксперимента можно один столбец оставить:

Иванов
Петров
Сидоров
Бандерас
Пангемон

На другом форуме мне предложили решение, но оно тоже завязано на идентификаторы. Я пока сделал выборку всех записей на SQL, а уже в PHP выбираю только нужное: получилось по-уродски, но работает. Всё-таки хочется красоты, а я уже слишком стар, чтобы решать такие головоломки :)

спустя 3 часа 5 минут [обр] Александр Галкин(0/211)[досье]
x28[досье]
Вместо идентификатора придумайте любой признак, по которому можно сортировать. Вы, наверное, пытаетесь выбрать «предыдущее» в порядке изменения строк, вот и сделайте поле с датой-временем последнего изменения.
спустя 28 минут [обр] Дмитрий Попов(17/509)[досье]
x28[досье]
Нельзя без идентификаторов. Вообще нельзя. Потому что это реляционная СУБД, которая не обещает Вам, что записи будут выводиться в том же порядке в котором они вставлены. Т.е. Ваше решение уже по определению неверно и неточно, потому что без наличия идентификаторов оно держится на "честном слове". Делайте хоть какой-то признак сортировки, и все станет проще. В конце концов действительно timestamp not null - однозначно решает, и его даже специально вставлять не надо будет (хотя если записи могут изменяться, то нужно меня его на другой тип)
спустя 17 часов [обр] x28[досье]

А! теперь понял. Значит важен порядок. Хорошо, я могу допустить в таблице, чтоб строковые записи (фамилии) хранились в алфавитном порядке:

Бандерас
Иванов
Пангемон
Петров
Сидоров

Теперь у записей есть заданный порядок.

Вот рабочий пример, который решает изначальную проблему, но он использует функцию MAX, поэтому если я откажусь от поля ID, этот пример не будет работать. Может быть можно как-нибудь модифицировать этот запрос? Есть ли в MySQL функции для преобразования строки в число?

$ENTRY_ID=2; // ID записи
$sql=" SELECT *
FROM `test`
WHERE IF( (
 
SELECT COUNT( * )
FROM `test`
WHERE `id` <$ENTRY_ID ORDER BY `id` ASC) >0, `id` = (
SELECT MAX( `id` )
FROM `test`
WHERE `id` <$_ENTRY_ID ORDER BY `id` ASC) , `id` = (
SELECT MAX( `id` )
FROM `test` )
) ";

спустя 3 часа 26 минут [обр] Александр Галкин(0/211)[досье]

x28[досье]

SELECT * FROM (
   (SELECT * FROM table WHERE name < 'Сидоров' ORDER BY name DESC LIMIT 1)
   UNION
   (SELECT * FROM table ORDER BY name DESC LIMIT 1)
) t
ORDER BY name LIMIT 1

Все подобные решения (без уникальных признаков) будут работать неправильно, если у вас в таблице будет, скажем, два Сидорова.

Было бы неплохо, если бы Вы описали свою задачу более конкретно, зачем вам понадобилось искать предыдущего, да ещё по таким странным критериям. Скорее всего существует более правильный подход.

спустя 45 минут [обр] x28[досье]

Попробую, объяснить задачу, которую я пытаюсь решить.
У меня на сайте есть список статей. В таблице, где они храняться есть поля id и title.
На сайте, при просмотре конкретной статьи внизу должны быть 2 ссылки, типа "похожие статьи".
Одна ссылка должна вести на следующую статью, если статьи в таблице отсортировать по id.
Вторас ссылка должна вести на следующую статью, если статьи отсортированы по title.

Пример.

Таблица, упорядоченная по id:
1 Как сделать закруглённые уголки
2 CSS-спрайты
3 Селекторы
4 Трёхколоночный макет
5 CSS-Хаки

Таблица упорядоченная по title:
2 CSS-спрайты
5 CSS-Хаки
1 Как сделать закруглённые уголки
3 Селекторы
4 Трёхколоночный макет

На странице "Как сделать закруглённые уголки":
Первая ссылка внизу ведёт на "CSS-спрайты"
Вторая ссылка внизу ведёт на "Селекторы"

На странице "Трёхколоночный макет":
Первая ссылка внизу ведёт на "CSS-Хаки"
Вторая ссылка внизу ведёт на "CSS-спрайты"

Надесь понятно объяснил, если нет — скажите.

Powered by POEM™ Engine Copyright © 2002-2005