K>Так вот, Id текущей записи я знаю, а как SQL запросом получить id следующей/предыдущей записей? K>таблица довольно большая — ~900000 записей.
Ничего страшного (fetch какой то.. ) тут нет, стандартная вещь,
лежащая в основе всех смотрелок..
Достаточно хорошо знать select http://www.mysql.com/doc/ru/SELECT.html
В таких случаях принято использовать
SELECT * from <your_fucking_table>
ORDER BY Id
LIMIT 1 OFFSET <your_offset>
При переходе на следующую запись просто увеличиваешь
<your_offset> на 1 и читаешь следующую запись..
Конечно, правильнее знать не текущий id, а именно номер записи в том порядке, в кортором его смотрит пользователь.. (<your_offset>)
это и ему удобнее..
Если же вы всё таки настаиваете на Id, то вам поможет
SELECT * from <your_fucking_table>
WHERE Id > <your_fucking_id>
ORDER BY Id
LIMIT 1
Здравствуйте, vvaizh, Вы писали:
V>Наверно я отвечу, уогда пойму, что именно вы имеете в виду под fetch
Получение слудующей(предыдущей — зависит от поддержки сервером bidirectional курсоров) записи из набора данных. Форма записи зависит от SQL сервера и языка(средства разработки) клиента
Здравствуйте, kastet, Вы писали:
K>Здравствуйте, vvaizh, Вы писали:
V>Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, vvaizh, Вы писали:
K>[skipped]
K>Спасибо за помощь. По документации все вроде сходится, но при выполнении
K>
K>SELECT * FROM `readers` ORDER BY READER_ID LIMIT 1 OFFSET 1
K>
K>MySQL выдает "You have an error in your SQL syntax near 'OFFSET 1' at line 1"
K>версия mysql 3.23.38, это проблема в руках или как?
Наверно в версии.. Вот что у меня на 4.0:
mysql> use test
Database changed
mysql> create table a(b int);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into a (b) values (1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into a (b) values (2);
Query OK, 1 row affected (0.00 sec)
mysql> insert into a (b) values (3);
Query OK, 1 row affected (0.01 sec)
mysql> insert into a (b) values (4);
Query OK, 1 row affected (0.00 sec)
mysql> select * from a order by b limit 1,1;
+------+
| b |
+------+
| 2 |
+------+
1 row in set (0.01 sec)
mysql> select * from a order by b limit 0,1;
+------+
| b |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> select * from a order by b limit 3,1;
+------+
| b |
+------+
| 4 |
+------+
1 row in set (0.00 sec)
mysql> select * from a order by b limit 1 offset 1;
+------+
| b |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
mysql> select * from a order by b limit 1 offset 2;
+------+
| b |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
Для очистки совечти попробуй вариант сзапятой (раз ему offset не нравится..)
И на всякий случай добавь ';' в конце..
K>Так вот, Id текущей записи я знаю, а как SQL запросом получить id следующей/предыдущей записей? K>таблица довольно большая — ~900000 записей.
ssm>Помоему корректней делать просто fetch
Чего-то я с утра туплю. Не подскажете как это корректно сделать в связке PHP+mySQL?
--- Если при помощи LIMIT выбираются только несколько строк, MySQL будет использовать индексы в тех некоторых случаях, когда он обычно предпочел бы делать полное сканирование таблицы.
--- Если LIMIT # используется с ORDER BY, MySQL закончит сортировку, как только найдет первые # строк, вместо того, чтобы сортировать всю таблицу.
Прошу заметить, что mySQL самая популярная база для WEB приложений, и подобные вопросы в ней давно уже апробированы и отработаны!
Здравствуйте, ssm, Вы писали:
V>Ничего страшного (fetch какой то.. ) тут нет, стандартная вещь, ssm>И что в нем страшного то?
Наверно я отвечу, уогда пойму, что именно вы имеете в виду под fetch
(т.е. для меня страшно то , что я не понимаю )
Так что был бы признателен за расширение своих горизонтов..
Лимит тут имхо не поможет. Речь идет о выборке записе согласно значениям колонки Id, как я понял. Лимит же выбирает опред. кол-во записей, к-е нужно выбрать. Поэтому при переходе на следующую запись можно просто указывать какой ид (а он, как я понял, уникален) нужен
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, vvaizh, Вы писали:
ВВ>Лимит тут имхо не поможет. Речь идет о выборке записе согласно значениям колонки Id, как я понял. Лимит же выбирает опред. кол-во записей, к-е нужно выбрать. Поэтому при переходе на следующую запись можно просто указывать какой ид (а он, как я понял, уникален) нужен
ВВ>
ВВ>SELECT * FROM fucking_table WHERE Id = 3
ВВ>
так то оно так, но вот что ты будешь делать, если запись с id=3 уже удалена, и следующий id=4?
вот для этого и нужен лимит, и условие >
Хотя как я уже говорил, правильнее ИМХО работать именно с offset..
так как тогда пользователю можно честно сказать: вы смотрите (n)-ю запись из
(select count(*) from fucking_table) что большинство смотрелок и делают
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, vvaizh, Вы писали:
ВВ>Лимит тут имхо не поможет. Речь идет о выборке записе согласно значениям колонки Id, как я понял. Лимит же выбирает опред. кол-во записей, к-е нужно выбрать.
Да, наверно я понял, вы опять не заметили offset... который как раз и даёт с какой записи по порядку выдавать результат..
Или наоборот заметили, и считаете, что offset не оптимизируется.. (хотя мог бы..)
Действительно в manual ничего не написано, как он оптимизируется.. Нужно проверять, может действительно второй мой вариант будет работать быстрее первого (там где явно написано Id>.. точно будет использоваться индекс..)
Хотя первый вариант я дейтствительно видел в стандартных смотрелках на php..
Здравствуйте, vvaizh, Вы писали:
V>Здравствуйте, kastet, Вы писали:
K>Здравствуйте, vvaizh, Вы писали:
V>Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, vvaizh, Вы писали:
K>[skipped]
V>Для очистки совечти попробуй вариант сзапятой (раз ему offset не нравится..) V>И на всякий случай добавь ';' в конце..
Здравствуйте, vvaizh, Вы писали:
V>Да, наверно я понял, вы опять не заметили offset... который как раз и даёт с какой записи по порядку выдавать результат.. V>Или наоборот заметили, и считаете, что offset не оптимизируется.. (хотя мог бы..) V>Действительно в manual ничего не написано, как он оптимизируется.. Нужно проверять, может действительно второй мой вариант будет работать быстрее первого (там где явно написано Id>.. точно будет использоваться индекс..)
Мне кажется, что второй твой вариант действительно будет быстрее. К тому же лимит там совершенно не нужен, так как лимитацию уже совершает WHERE. Ведь ID должен быть уникальным (в противном случае теряется самый смысл идентификации) и соответственно будет совершена выборка не более одной записи.
Впрочем, по поводу быстроты — это имхо, основанное на собственном опыте применения.
А вообще мне кажется, что все разногласия из-за того, что автора первого поста не совсем ясно сформулировал что ему надо. Совершать последовательную выборку это одно, а делать выборку по значению полей — совсем другое.
ВВ>Мне кажется, что второй твой вариант действительно будет быстрее. К тому же лимит там совершенно не нужен, так как лимитацию уже совершает WHERE. Ведь ID должен быть уникальным (в противном случае теряется самый смысл
Да но условию скажем ID>4
Могут удовлетворять __уникальные__ id 5,6,7..
А нам нужен именно первый из них..
Здравствуйте, vvaizh, Вы писали:
V>Да но условию скажем ID>4 V>Могут удовлетворять __уникальные__ id 5,6,7.. V>А нам нужен именно первый из них..
Че-то я уже не въезжаю. Мне нужна запись с ИД>4 и притом одна. Так почему сразу ее явно не запросить, т.е. запись с ИД=5. Ты сам посуди какое у тебя условие.
Ид должно быть больше 4, запись с Ид должна быть только одна, из всех записей с Ид больше четырех, должна быть выбрана та, Ид которой максимально приближено к 4.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, vvaizh, Вы писали:
V>Да но условию скажем ID>4 V>Могут удовлетворять __уникальные__ id 5,6,7.. V>А нам нужен именно первый из них..
ВВ>Че-то я уже не въезжаю. Мне нужна запись с ИД>4 и притом одна. Так почему сразу ее явно не запросить, т.е. запись с ИД=5. Ты сам посуди какое у тебя условие.
ВВ>Ид должно быть больше 4, запись с Ид должна быть только одна, из всех записей с Ид больше четырех, должна быть выбрана та, Ид которой максимально приближено к 4.
ВВ>Не проще ли заменить все это на:
ВВ>Ид должно быть равно 5.
Т.е. когда то в ней и был id==5, но потом кто-то эту запись удалил..
Одну из 900000 ....
НЕ перенумеровывать же из-за этого все id..
В существующих базах данных это не принято..
Так работают всякие auto-increment поля и sequence..
Поэтому нужно именно то что я написал..
Это только он в своём примере написал что у него id по порядку идут, в реальности это не так!
Здравствуйте, vvaizh, Вы писали:
V>Поэтому нужно именно то что я написал.. V>Это только он в своём примере написал что у него id по порядку идут, в реальности это не так!
Так речь-то именно о его примере! В том-то и вопрос. А ты начинаешь "принимать по умолчанию" ряд условий, которых изначально не было. Если база данных динамически обновляется, то всяко может быть в принципе. Даже запрос типа:
SELECT * FROM fucking_table WHERE Id > 4 LIMIT 1
Может жахнуть по причине отсуствия таковых полей (соответственно по причине их удаления). Дык по Ид в таком случае вообще уже нельзя. Т.е. суть в чем: если я знаю, какие поля точно есть, тогда можно без лимита; если я вообще это не знаю, тогда бредово в принципе использовать статические значения полей в каком бы то ни было виде. А если знаю, что поле Ид 5 точно есть, то следующие запросы будут идентичны:
ВВ>Так речь-то именно о его примере! В том-то и вопрос. А ты начинаешь "принимать по умолчанию" ряд условий, которых изначально не было. Если база данных динамически обновляется, то всяко может быть в принципе. Даже запрос типа:
Совершенно верно, я исхожу из своего опыта, и как вижу из отзывов "попал в точку.."
Так как это очень распространённая задача (в каком то виде она как правило решается ___везде___)
Любая табличка, отображающая базу данных должны уметь это делать..
Любая форма-страница с возможностью навигации..
Я даже не знаю обратных примеров..
ВВ>Может жахнуть по причине отсуствия таковых полей (соответственно по причине их удаления). Дык по Ид в таком случае вообще уже нельзя.
Выкинуть колонку ID может по правильному только администратор базы данных, который в этом случае несёт также ответственность и за все запросы, которые он должен переписать...
Удалить же запись с id=5 может как правило пользователь!
И все запросыы при этом должны продолжать работать (т.е. по правильному пльзователь не может повалить базу..)
Здравствуйте, vvaizh, Вы писали:
V>Выкинуть колонку ID может по правильному только администратор базы данных, который в этом случае несёт также ответственность и за все запросы, которые он должен переписать... V>Удалить же запись с id=5 может как правило пользователь! V>И все запросыы при этом должны продолжать работать (т.е. по правильному пльзователь не может повалить базу..)
Ты немного не понял. речь не о том, что выкинуть всю колонку, а том, чтобы удалить ряд записей. Если есть 10 записей, то при этом пользователь удаляет все записи от 5, вот тогда и будет. Конечно бороться с этим можно, но сам подход для последовательной выборки довольно странный.
В общем я к тому, что последовательная выборка всегда осуществляется средствами ридера. В АДО — это метод Read и пр.
Здравствуйте, Воронков Василий, Вы писали:
ВВ>Здравствуйте, vvaizh, Вы писали:
V>Выкинуть колонку ID может по правильному только администратор базы данных, который в этом случае несёт также ответственность и за все запросы, которые он должен переписать... V>Удалить же запись с id=5 может как правило пользователь! V>И все запросыы при этом должны продолжать работать (т.е. по правильному пльзователь не может повалить базу..)
ВВ>Ты немного не понял. речь не о том, что выкинуть всю колонку, а том, чтобы удалить ряд записей. Если есть 10 записей, то при этом пользователь удаляет все записи от 5, вот тогда и будет.
Запрос сработает и в этом случае, он вернёт пустую выборку..
Тут всё дело в блокировках, если в ВЕБ-приложениях позволять каждому юзеру что то блокировать на сервере в течении сессии, то это плохо кончится, поэтому так не делают..
ВВ>Конечно бороться с этим можно, но сам подход для последовательной выборки довольно странный. ВВ>В общем я к тому, что последовательная выборка всегда осуществляется средствами ридера. В АДО — это метод Read и пр.
Ну а они то по итогу как по твоему работают?
Всё равно через SQL!
для T-SQL это keyword TOP!
Тут ещё предлагалось использовать cursor-ы
(которые возможно использовать и для твоего Read)
Но, во первых на mySQL нет курсоров, а во вторых они предполагают затраты ресурсов на стороне сервера в течении всего существования сессии, что для WEB-приложния плохо (с течением времени это сильно замедляет скорость работы сервера), так что тут лучше обойтись простым запросом — сделал, забыл (в сессии на стороне сервера ничего хранить не нужноюю)
Здравствуйте, vvaizh, Вы писали:
V>Тут ещё предлагалось использовать cursor-ы V>(которые возможно использовать и для твоего Read) V>Но, во первых на mySQL нет курсоров, а во вторых они предполагают затраты ресурсов на стороне сервера в течении всего существования сессии, что для WEB-приложния плохо (с течением времени это сильно замедляет скорость работы сервера), так что тут лучше обойтись простым запросом — сделал, забыл (в сессии на стороне сервера ничего хранить не нужноюю)
Кстати, это уже интересный вопрос. Что собственно лучше. лучше ли использовать один раз дебильный запрос вроде SELECT * FROM fucking_table, а затем продвигаться по записям ридером. Или же для передвижения по записям использовать каждый раз новый запрос.
ВВ>Кстати, это уже интересный вопрос. Что собственно лучше. лучше ли использовать один раз дебильный запрос вроде SELECT * FROM fucking_table, а затем продвигаться по записям ридером.
Ещё раз напоминаю, речь идёт о веб приложении...
в этом случае, вы свой риадер должны будете завобдить в сессии..
т.е. зашло 1000 пользователей..
на каждый система завела по ридеру..
пользователи пошли курить..
ридеры будут торчать ещё несколько минут..
В моём случае, сервер может использовать вообще 1 коннектион на всех пользователей, и соотв.
Возможности масштабирования гораздо богаче ..
Что нагладно демонстрирует Google..
Если бьы он заводил reader на каждого кто ищет, и держал бы его пока человеку не надоест (и ещё несколько минут после этого) ТАКОЙ скорости мы не увидали бы..
ВВ>Или же для передвижения по записям использовать каждый раз новый запрос.
Ещё раз повторяю, это — сложившаяся общепринятая практика для ___WEB___приложений..!
Здравствуйте, vvaizh, Вы писали:
ВВ>>Или же для передвижения по записям использовать каждый раз новый запрос. V>Ещё раз повторяю, это — сложившаяся общепринятая практика для ___WEB___приложений..!
Я не спорю, что сложившаяся. Сам я никогда такой выборки, какую автор первого поста описал, в веб не делал, не приходилось как-то.
Вопрос был собственно общий. Не как это для веба, а как это вообще. В плане оптимизации разумеется. В смысле your opinion.