2010-07-29 2 views
2

Возможно ли разбиение на страницы и отображение количества страниц в Coldfusion с использованием только одного запроса?Paginating with Coldfusion

Насколько я понимаю, вы можете, очевидно, разбивать страницы на один запрос, но вам нужен дополнительный запрос для создания страниц. Это позволяет рассчитать общее количество результатов.

(currentPage - 1) * resultsPerPage = Offset in MySQL запрос. Эта логика достаточна для создания кнопок next/prev. Но для того, чтобы узнать количество страниц, нам не нужно было бы знать общее количество результатов, используя отдельный запрос, а затем запрос запросов к данным?

ответ

2

Да, типичный метод на основе mysql нуждается в двух запросах: один с select count(*) from table, второй с select a, b, c from table limit x,y где x и y строятся в зависимости от текущей страницы и необходимого смещения.

С одним запросом вам нужно будет выбрать все записи, которые менее эффективны в самых случаях.

+0

Лично я всегда ставил запрос на кеш на счетчик (*). В зависимости от обычной частоты изменений данных он может кэшироваться от 30 секунд до нескольких часов. Затем верните структуру с полным и вычисленным набором данных. –

2

У меня не так много знакомство с MySQL, но я знаю, что в MS SQL хранимая процедура может возвращать несколько наборов результатов.

Если вы не можете сделать это, вы можете предложить два способа, но второй можно оптимизировать.

Сначала запустите два запроса. Один, чтобы получить данные для текущей отображаемой страницы, чтобы получить общий размер набора результатов. Это то, что я сделал бы, если данные будут меняться часто или если несколько страниц обычно не отображаются. Это требует двух вызовов db, но уменьшает общий размер возврата. Если вы не меняете данные часто, но редко используете более нескольких страниц на запрос, вы также можете кэшировать общий результат.

Второе - вернуть все результаты в один большой запрос и отобразить только соответствующую страницу. Здесь вам не нужен запрос запросов, поскольку циклы запросов с использованием cfloop и cfoutput могут указывать начальные и конечные строки запросов. Если вы сделаете это, я буду кэшировать запрос. Это использует больше памяти, и загрузка первой страницы будет медленнее, но на последующих страницах у вас будут быстрые загрузки страниц.

3

В MS SQL, используйте КТР:

получить аргументы @startRow и @endRow плюс ваши необходимые аргументы

WITH qTemp AS (
    select * 
    , count(*) as totCnt 
    , rowNum = ROW_NUMBER() OVER(ORDER BY myIndex ASC) 
    from myTable 
    where (my where clause) 
) 
SELECT * FROM qTemp 
WHERE rowNum BETWEEN @startRow AND @endRow 
+1

Я бы дал это +1, за исключением вопроса о MySQL. –

2

То, что я сделал это сделать «большой» запрос и сохранить результаты в области SESSION, а затем выполнить запрос запроса на каждой странице. Меньше вызовов в базу данных, которая обычно находится там, где узкие места в любом случае.

1

Я считаю, что вы можете сделать:

SET @myCount = (SELECT COUNT(*) FROM tblName); 

SELECT col1, col2, @myCount as 'total' 
FROM tblName 

С вашим соответствующим постраничным материалом в месте на втором запросе. Вы получите счет на каждую запись в возвращаемом наборе, но это не очень важно. Я не тестировал это, но у меня нет MySQL.

1

В то время как это не самый лучший способ сделать это, это старый школьный путь.

вы можете выполнить это, используя cfoutput.

<cfquery name="q" dsn="#application.dsn"> 
SELECT 
    firstname, 
    lastname 
FROM 
    mytable 
WHERE 
    <some conditions> 
</cfquery> 

<cfparam name="url.maxrows" default="50"> 
<cfset url.maxrows = fix(val(url.maxrows))> 
<cfparam name="url.startrow" default="1"> 
<cfset url.startrow = fix(val(url.startrow))> 
<cfif url.startrow lte 0> 
    <cfset url.startrow = 1> 
</cfif> 
<cfif url.startrow gte q.recordcount> 
    <cfset url.startrow = q.recordcount> 
</cfif> 

<cfoutput>Total Records: #q.recordcount#/<cfoutput> 

<cfoutput query="q" maxrows="#url.maxrows#" startrow="#url.startrow#"> 
    #firstname#<br/>#lastname# 
</cfoutput> 

<p>Page: 
<cfloop from="1" to="#q.recordcount#" step="#url.maxrows#" index="i"> 
    <a href="#cgi.script_name#?startrow=#i#&maxrows=#url.maxrows">#(i/url.maxrows)#</a> 
</cfloop> 
</p> 

теперь, если честно ... этот метод сосет и ДЕЙСТВИТЕЛЬНО замедляется для больших запросов. лично я использую CFWheels, который имеет весь этот материал built into it's ORM.

+0

rip747, какое влияние на производительность можно ожидать, если использовать фреймворк, а не традиционный метод? – Mohamad

+0

@mel - колеса очень легкие, поэтому вам не нужно беспокоиться о производительности, вы, вероятно, не заметите разницы вообще. на оборотной стороне, хотя, я с радостью обменяю несколько миллисекунд на скорость разработки в колесах. – rip747

1

В MySQL используется SQL_CALC_FOUND_ROWS. Например:

SELECT SQL_CALC_FOUND_ROWS * FROM tbl WHERE x = y LIMIT s,m 

Сразу после запроса запроса снова:

SELECT FOUND_ROWS() AS TotalRows 

Использование директивы SQL_CALC_FOUND_ROWS заставляет MySQL, чтобы сохранить общее количество строк, найденных в последнем запросе перед нанесением предела и диапазона. Это то же самое, что делать Count() в том же запросе без накладных расходов, на самом деле приходится рассчитывать, а затем запрашивать, ограничивать запрос.

Оберните два вызова db в транзакции, чтобы обеспечить их выполнение последовательно. Вы могли бы также подумать об абстрагировании запросов в функцию, которая будет делать и то и другое, и возвращать одну структуру с ключом результатов и полными ключами строк. Используйте приведенные выше результаты для создания ссылок на страницы, как вы сочтете нужным.

2

Как правило, я это делаю. Вы можете выбрать счетчик таблицы, выполнив подвыбор и наложив на него псевдоним. Вы можете видеть это как третий класс в этом запросе. Это можно использовать для захвата данных из другой таблицы, если хотите. это заставляет MySQL инициировать другой запрос в середине вашего запроса для сбора данных, но coldfusion требует только спросить базу данных, когда она делает это быстрее, чем 2 отдельных запроса.

<cfquery name="SomeQry" datasource="YourDatabase"> 
    SELECT 
    col1, 
    col2, 
    (SELECT COUNT(*) FROM MyTable) as mycount 
    FROM MyTable 
    LIMIT #(CurrentPage * 20) - 20#, 20 
</cfquery> 

     <cfset start = CurrentPage - 5> 
     <cfset Max = CurrentPage + 5> 

     <cfoutput> 
      <ul class="pagination"> 
       <cfloop from=#start# to=#Max# index="page"> 
        <li><a href="https://stackoverflow.com/search?q=#querystring#&page=#page#">#page#</a></li> 
      </cfloop> 
      </ul> 
     </cfoutput>