Справка по нумерации страниц в SQL - PullRequest
0 голосов
/ 18 февраля 2009

Нижеследующий внутренний SELECT возвращает огромное количество строк (1000000+), а внешние SELECT (альфа BETWEEN # startRec # AND # endRec #) используются для PAGINATION для отображения данных с 25 на каждой странице.

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

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

/*********ORIGINAL QUERY ****/
SELECT
*
FROM 
(
SELECT
beta.*, rownum as alpha
FROM
(
SELECT 
p.lastname, p.firstname, porg.DEPARTMENT,
porg.org_relationship,
porg.enterprise_name,
(
SELECT 
count(*) 
FROM 
test_person p, test_contact c1, test_org_person porg 
WHERE 
p.p_id = c1.ref_id(+) 
AND p.p_id = porg.o_p_id 
$where_clause$


) AS results
FROM 
test_person p, test_contact c1, test_org_person porg
WHERE 
p.p_id = c1.ref_id(+) 
AND p.p_id = porg.o_p_id 
$where_clause$ 


ORDER BY 
upper(p.lastname), upper(p.firstname)
) beta
)
WHERE
alpha BETWEEN #startRec# AND #endRec#

Моя проверенная реализация ниже


(1) Самый внутренний запрос ... это первый запрос, извлекающий данные. (2) Затем, мы делаем общий подсчет на вышеуказанных данных.

Теперь главная проблема - выполнение запроса продолжается вечно ... и, наконец, я вынужден принудительно отменить его. Я чувствую, что в приведенном ниже запросе чего-то не хватает, для чего это зависает.

Кроме того, я узнал, что использование COUNT вне системы - это лучший подход к производительности. Итак, не могли бы вы исправить приведенный ниже запрос, чтобы я мог вернуть COUNT *** ДАННЫЕ с использованием пагинации, rownum и т. Д. В основном с псевдонимами ниже, rownum и получением данных.

select * from 
( select x.* ,rownum rnum 

from ( SELECT 
count(*) as results /****2nd QUERY is OUTSIDE to get total count**/

Вопрос здесь, как мне получить доступ к данным, выбранным в 1-м запросе ниже

from ( /****1st query to SELECT data***/


SELECT 
p.lastname, p.firstname, porg.DEPARTMENT,
porg.org_relationship,
porg.enterprise_name

FROM 
t_person p, t_contact c1, t_o_person porg 
WHERE rownum <10
and
p.person_id = c1.ref_id(+) 
AND p.person_id = porg.o_person_id 



ORDER BY 
upper(p.lastname), upper(p.firstname)



) y ------------------>alias defined Y from data of the 1st query


)x ------------------>alias defined X 
where rownum <= 20 )
where rnum >= 1

Ответы [ 7 ]

2 голосов
/ 19 февраля 2009

Может быть, я что-то пропустил, но рассматривали ли вы условия LIMIT и OFFSET? http://www.sql.org/sql-database/postgresql/manual/queries-limit.html

2 голосов
/ 19 февраля 2009

Чтобы быстро выполнить разбиение на страницы, необходимо ограничить возвращаемые результаты запроса. например. в mysql вы можете использовать limit и calc_rows.

Вы должны проверить свою БД, однако было бы проще разбить эти 2 на отдельные запросы, если у вас нет этих вспомогательных функций.

1 голос
/ 19 февраля 2009

Какую базу данных вы используете? Если Oracle, идеи, предложенные другими, не будут работать, Oracle не поддерживает синтаксис LIMIT для SQL.

Для Oracle вы заключаете запрос в следующий синтаксис:

SELECT * 
FROM (SELECT a.*, 
             ROWNUM rnum 
      FROM ( [your query] ) a 
      WHERE ROWNUM <= [endRow] ) 
WHERE rnum >= [startRow]
1 голос
/ 19 февраля 2009

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

-- get page of data
SELECT *
FROM
(
    SELECT 
        p.lastname, p.firstname, porg.DEPARTMENT,
        porg.org_relationship,
        porg.enterprise_name
    FROM 
        test_person p, test_contact c1, test_org_person porg
    WHERE 
        p.p_id = c1.ref_id(+) 
        AND p.p_id = porg.o_p_id 
        $where_clause$ 
    ORDER BY 
    upper(p.lastname), upper(p.firstname)
) beta
WHERE
rownum BETWEEN #startRec# AND #endRec#

--get total count
SELECT count(*) as Count
FROM 
    test_person p, test_contact c1, test_org_person porg
WHERE 
    p.p_id = c1.ref_id(+) 
    AND p.p_id = porg.o_p_id 
    $where_clause$ 

Вы также можете вернуть общее количество в первой строке данных в ваших результатах, например:

SELECT null, null, null, null, null, count(*) as Count
FROM 
    test_person p, test_contact c1, test_org_person porg
WHERE 
    p.p_id = c1.ref_id(+) 
    AND p.p_id = porg.o_p_id 
    $where_clause$ 

UNION ALL

SELECT *
FROM
(
    SELECT 
        p.lastname, p.firstname, porg.DEPARTMENT,
        porg.org_relationship,
        porg.enterprise_name, null
    FROM 
        test_person p, test_contact c1, test_org_person porg
    WHERE 
        p.p_id = c1.ref_id(+) 
        AND p.p_id = porg.o_p_id 
        $where_clause$ 
    ORDER BY 
    upper(p.lastname), upper(p.firstname)
) beta
WHERE
rownum BETWEEN #startRec# AND #endRec#
0 голосов
/ 04 марта 2009

В Oracle есть несколько вариантов:

  1. Использование ROWNUM во внутреннем запросе с переносом для получения нумерации страниц (как вы уже пытались)
  2. Использование аналитических функций.

Оба подхода хорошо описаны Томом Кайтом:

http://www.oracle.com/technology/oramag/oracle/07-jan/o17asktom.html

Надеюсь, это поможет.

0 голосов
/ 19 февраля 2009

Мое предложение:

  • Создать индекс для test_person по фамилии + имени (в этом порядке)
  • Если возможно, удалите верхние функции (некоторые БД позволяют создавать индексы с использованием функций)
  • Удалить внешний SELECT и выполнить нумерацию страниц в клиенте (не в БД)

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

Приветствия

0 голосов
/ 19 февраля 2009

Они специально предназначены для ASP, но могут быть легко адаптированы: http://databases.aspfaq.com/database/how-do-i-page-through-a-recordset.html Лично я реализовал метод хранимой процедуры "#Temp table", когда недавно мне понадобилось решение для пейджинга.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...