2015-04-07 3 views
8

У меня есть веб-приложение, в котором я показываю серию сообщений на основе этой схемы таблиц (есть тысячи строк, подобных этому и другим столбцам тоже (удалены как не требуемые для этого вопроса)) : -Как это запросить в mysql

+---------+----------+----------+ 
| ID | COL1 | COL2 | 
+---------+----------+----------+ 
| 1  | NULL | ---- | 
| 2  | --- | NULL | 
| 3  | NULL | ---- | 
| 4  | --- | NULL | 
| 5  | NULL | NULL | 
| 6  | --- | NULL | 
| 7  | NULL | ---- | 
| 8  | --- | NULL | 
+---------+----------+----------+ 

И я использую этот вопрос: -

SELECT * from `TABLE` WHERE `COL1` IS NOT NULL AND `COL2` IS NULL ORDER BY `COL1`; 

И результирующий набор результатов я получаю, как: -

+---------+----------+----------+ 
| ID | COL1 | COL2 | 
+---------+----------+----------+ 
| 12 | --- | NULL | 
| 1  | --- | NULL | 
| 6  | --- | NULL | 
| 8  | --- | NULL | 
| 11  | --- | NULL | 
| 13  | --- | NULL | 
| 5  | --- | NULL | 
| 9  | --- | NULL | 
| 17 | --- | NULL | 
| 21 | --- | NULL | 
| 23 | --- | NULL | 
| 4  | --- | NULL | 
| 32 | --- | NULL | 
| 58 | --- | NULL | 
| 61 | --- | NULL | 
| 43 | --- | NULL | 
+---------+----------+----------+ 

Обратите внимание, что столбец идентификаторов смешался в соответствии с предложением order by.

У меня есть соответствующие индексы для оптимизации этих запросов. Теперь позвольте мне объяснить настоящую проблему. В моем веб-приложении у меня есть ленивая функция. Итак, я показываю около 10 сообщений на странице, используя LIMIT 10 после запроса первой страницы.

Мы хорошо до сих пор. Но реальная проблема возникает, когда мне приходится загружать вторую страницу. Что я сейчас запрашиваю? Я не хочу, чтобы сообщения повторялись. И появляются новые сообщения, которые появляются почти каждые 15 секунд, что заставляет их идти сверху (сверху буквально означает первую строку) набора результатов (я не хочу отображать эти последние сообщения на второй или третьей странице, но они изменяют поэтому я не могу использовать LIMIT 10,10 для 2-й страницы и так далее, поскольку сообщения будут повторяться.).

Теперь, все, что я знаю, это последний идентификатор сообщения, которое я отобразил. Скажите 21 здесь. Итак, я хочу отображать сообщения ID 23,4,32,58,61,43 (см. Таблицу результатов выше). Теперь загрузите все строки без использования предложения LIMIT и отобразите 10 идентификаторов, возникших после id 21. Но для этого мне придется взаимодействовать с тысячами бесполезных строк. Но я не могу использовать предложение LIMIT для 2-й, 3-й ... страниц, что точно. Кроме того, идентификаторы смешаны, поэтому я определенно не могу использовать WHERE ID>.... Итак, куда мы теперь пойдем?

+0

Поскольку ваш 'COL1' является сортируемым, как насчет того, чтобы запомнить последнюю запись' COL1' в каждом запросе, а на следующей странице загружать 'WHERE COL1>?'? – Passerby

+0

@ Пассерби, я об этом уже подумал. Но у 'COL1' много одинаковых строк. На самом деле, 'COL1' является меткой времени, и многие строки могут иметь одну и ту же метку времени (в моем наборе результатов) – user4647309

ответ

2

Хмм .. Я подумал немного и придумал 2 решения. : -

  1. Чтобы сохранить идентификаторы поста уже отображается и запрос WHERE ID NOT IN(id1,id2,...). Но это потребует дополнительной памяти. И если пользователь загружает 100 страниц, а идентификаторы - в 100000, тогда один запрос GET не сможет его обработать. По крайней мере, не во всех браузерах. Можно использовать запрос POST.

  2. Alter, как вы видите сообщения от COL1. Я не знаю, хорошо ли это для вас. Но это может сэкономить вам ленту и сделать ваш код чище. Это также может быть лучшим способом. Я бы предложил следующее: - SELECT * from TABLE where COL1 IS NOT NULL AND COL2 IS NULL AND Id>.. ORDER BY ID DESC LIMIT 10,10. Это может повлиять на то, как вы показываете свои сообщения по прыжкам и ограничениям. Но, как вы сказали в своих комментариях, что вы проверяете, соответствует ли сообщение критериям и меняет COL1 с NULL на текущий timestammp, я предполагаю, что чем больше сообщений, тем выше вы хотите их отображать. Это просто идея.

+0

Я уже пробовал первый метод раньше. Но он не счел это очень выполнимым. Но, я думаю, что я могу попробовать ваш второй метод. Спасибо +1 – user4647309

3

Я не уверен, если я правильно понял ваш вопрос, но вот как я думаю, что я хотел бы сделать это:

  • Добавьте столбец временной метки в таблицу, давайте назовем его date_added
  • Когда показывая на первой странице, используйте свой запрос as-is (с LIMIT 10) и держитесь за отметку времени самой последней записи; назовем это last_date_added.
  • Для 2-го, 3-го и последующих страниц, изменить ваш запрос, чтобы отфильтровать все записи с date_added > last_date_added и использовать LIMIT 10, 10, LIMIT 20, 10, LIMIT 30, 10 и так далее.

Это приведет к замораживанию вашего набора результатов во времени и сбросу его при каждом первом доступе к первой странице.

Примечания:

  • В зависимости от порядка вашего результирующем, возможно, потребуется отдельный запрос для получения last_date_added. В качестве альтернативы вы можете просто отключиться в текущее время, то есть время доступа к первой странице.
  • Если ваши идентификаторы являются последовательными, вы можете использовать тот же трюк с идентификатором.
+0

Забавно, что столбец' COL1' является меткой времени. Но, к сожалению, как я уже упоминал в комментарии выше, он не совсем уникален, так как многие строки имеют одну и ту же метку времени. Я проверяю, соответствует ли сообщение критериям и изменяет значение «COL1» с NULL на текущий timestammp. Поэтому, если многие сообщения соответствуют критериям, они имеют одинаковую временную метку. – user4647309

+0

@ user4647309 Итак, почему бы не добавить дополнительную временную метку date_added, которая устанавливается при вставке записи? Если вы используете точность микросекунды, она должна быть довольно уникальной. Или, как я уже сказал, если ваши идентификаторы являются последовательными, перед выполнением запроса для первой страницы вы можете получить самый высокий идентификатор и использовать это, чтобы заморозить набор результатов для последующих страниц. –

+2

@RobbyCornelissen Я думаю, проблема в том, что сортировка по 'COL1' будет« рушить »порядок сортировки' ID' или любой подобной вещи: с тем же 'COL1' это может помочь, но' WHERE \ 'ID \'> ? 'также отфильтровывает некоторый результат, который имеет более высокий' COL1', но более низкий 'ID'. – Passerby

1

Я предполагаю, что новые сообщения будут добавлены с более высоким идентификатором, чем текущий максимальный ID справа? Так что вы не могли бы просто запустить ваш запрос и захватить текущий максимальный ID. Затем, когда вы запрашиваете страницу 2, выполняйте тот же запрос, но с «ID < max_id». Это должно дать вам тот же результат, что и ваш запрос на странице 1, потому что у любых новых строк будет ID> max_id. Надеюсь, это поможет?

1

Как насчет?

ORDER BY `COL1`,`ID`; 

Это всегда будет приводить ID на заказ. Это позволит вам использовать:

LIMIT 10,10 

для вашей второй страницы.

Смежные вопросы