Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Как выбрать данные в одном запросе с количеством строк?  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Для постраничного вывода данных необходимо подсчитать количество строк, удовлетворяющих условиям некого фильтра. В итоге выполняются два запроса: Первый вида SELECT COUNT(*) FROM ... WHERE ... и потом собственно сами данные SELECT * FROM ... WHERE ...

Возник вопрос, нельзя ли это все сделать одним запросом?
22 май 12, 18:01    [12596595]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
Dmitry V. Liseev
Для постраничного вывода данных необходимо подсчитать количество строк, удовлетворяющих условиям некого фильтра. В итоге выполняются два запроса: Первый вида SELECT COUNT(*) FROM ... WHERE ... и потом собственно сами данные SELECT * FROM ... WHERE ...

Возник вопрос, нельзя ли это все сделать одним запросом?


а как результат этого одного запроса должен выглядеть?
22 май 12, 18:06    [12596621]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Baddy
Member

Откуда: Харьков
Сообщений: 174
select COUNT (*) over(partition by 1), *
from...
where...
22 май 12, 18:11    [12596652]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Ural2
Member

Откуда:
Сообщений: 58
Сформулируйте точнее, что нужно получить.
Может это:
SELECT field1, field2, COUNT(*) as count 
FROM ... 
WHERE ... 
GROUP BY field1, field2
22 май 12, 18:16    [12596672]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
Baddy, можно и без partition by 1
22 май 12, 18:29    [12596734]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Baddy
Member

Откуда: Харьков
Сообщений: 174
Shakill
Baddy, можно и без partition by 1

таки можно. привычка)
22 май 12, 18:31    [12596749]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Shakill
а как результат этого одного запроса должен выглядеть?
Как угодно, лишь бы два раза не делать одну работу.
23 май 12, 14:21    [12601313]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Ural2
Сформулируйте точнее, что нужно получить.
Может это:
SELECT field1, field2, COUNT(*) as count 
FROM ... 
WHERE ... 
GROUP BY field1, field2
GROUP BY не пойдет. Нужно получить все строки, но постранично. И при этом знать общее количество строк.
23 май 12, 14:38    [12601525]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
Dmitry V. Liseev
Shakill
а как результат этого одного запроса должен выглядеть?
Как угодно, лишь бы два раза не делать одну работу.

под работой вы понимаете написание два раза одинаковых секций FROM и WHERE или что-то другое?
23 май 12, 14:49    [12601684]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Shakill
под работой вы понимаете написание два раза одинаковых секций FROM и WHERE или что-то другое?
Я понимаю затраты ресурсов сервера на выполнение двух почти одинаковых запросов подряд. Хотелось бы выполнить запрос один раз, посчитать количество строк, которые удовлетворяют WHERE, вернуть это клиенту, а потом еще сделать пейджинг, т.е. отсортировать по заданным критериям и вернуть клиенту строки со 100 до 150 из результатов первого запроса (порядок нумерации строк, понятно, зависит от критериев сортировки).
24 май 12, 13:03    [12607680]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
RubinDm
Member

Откуда:
Сообщений: 461
Dmitry V. Liseev, зачем вам количество записей? Вы собираетесь показывать скролл-бар по вертикали?
24 май 12, 13:28    [12607873]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
RubinDm
Member

Откуда:
Сообщений: 461
[quot Dmitry V. Liseev]
Shakill
затраты ресурсов сервера на выполнение двух почти одинаковых запросов подряд

Сколько на самом деле уходит времени на выполнение каждого запроса?
24 май 12, 13:30    [12607886]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
Dmitry V. Liseev
Shakill
под работой вы понимаете написание два раза одинаковых секций FROM и WHERE или что-то другое?
Я понимаю затраты ресурсов сервера на выполнение двух почти одинаковых запросов подряд. Хотелось бы выполнить запрос один раз, посчитать количество строк, которые удовлетворяют WHERE, вернуть это клиенту, а потом еще сделать пейджинг, т.е. отсортировать по заданным критериям и вернуть клиенту строки со 100 до 150 из результатов первого запроса (порядок нумерации строк, понятно, зависит от критериев сортировки).


то есть первый запрос должен вернуть количество всех записей, удовлетворяющих пользовательскому условию, а второй запрос вернет данные, удовлетворяющие этому условию плюс условию пейджинга - и тут вы на чем-то желаете сэкономить? сомнительно
24 май 12, 13:38    [12607943]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
denis2710
Member

Откуда: Москва
Сообщений: 3384
а что насчет
SELECT * FROM ... WHERE ...
а потом
@@RowCount
не?
24 май 12, 15:03    [12608688]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Shakill
то есть первый запрос должен вернуть количество всех записей, удовлетворяющих пользовательскому условию, а второй запрос вернет данные, удовлетворяющие этому условию плюс условию пейджинга - и тут вы на чем-то желаете сэкономить? сомнительно
А в чем принципиальная невозможность?
8 июн 12, 12:57    [12687118]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
denis2710
а что насчет
SELECT * FROM ... WHERE ...
а потом
@@RowCount
не?
Нет. RowCount выдает количество возвращаемых записей после пейджинга. А мне нужно знать после пользовательской фильтрации, но до пейджинга.
8 июн 12, 13:00    [12687150]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
Dmitry V. Liseev, в том что эти запросы - разные. и сооружать из них один общий смысла нет, т.к. по большому счету вы ничего не выиграете, а вот исходник для понимания усложните
8 июн 12, 13:02    [12687173]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Shakill
Dmitry V. Liseev, в том что эти запросы - разные. и сооружать из них один общий смысла нет, т.к. по большому счету вы ничего не выиграете, а вот исходник для понимания усложните
Представьте, что Вы показываете юзеру грид с пейджингом. Юзер настраивает сложный фильтр, правила сортировки, может указать конкретную страницу пейджинга.

1. Грид собирается из кучи таблиц при помощи join.
2. Применяется сложный фильтр (на это и уходит основное время).
3. Cортируется, как указал пользователь.
4. Строки нумеруются при помощи ROW_NUMBER().
5. Выполняется условие пейджинга, которое выдает из результата нужную страницу (записи с номерами строк из заданного диапазона).
6. Набор строк возвращается клиенту.

Проблема в том, что нам нужно знать, сколько страниц всего. Для этого выполняется второй запрос:

1. Грид собирается из кучи таблиц при помощи join.
2. Применяется сложный фильтр (на это и уходит основное время).
3. Подсчитывается количество строк при помощи count(*).
4. Число возвращается клиенту.

Пункты 1 и 2 в обоих запросах одинаковы, а выполнять их нужно подряд друг за другом.

Теоретически, можно попробовать так:

1. Грид собирается из кучи таблиц при помощи join.
2. Применяется сложный фильтр (на это и уходит основное время).
3. Первичные ключи отобранных записей складываются во временную таблицу.
4. Подсчитывается количество строк во временной таблице.
5. Число возвращается клиенту.

6. Грид заново собирается из кучи таблиц + еще временной с inner join по первичным ключам (т.е. заново фильтровать не нужно).
7. Cортируется, как указал пользователь.
8. Строки нумеруются при помощи ROW_NUMBER().
9. Выполняется условие пейджинга, которое выдает из результата нужную страницу (записи с номерами строк из заданного диапазона).
10. Набор строк возвращается клиенту.

Идея в том, что, поскольку в фильтрах в основном like и индексы бесполезны, если фильтровать не два раза а один, то скорость возрастет ровно вдвое. Что думаете по этому поводу?
8 июн 12, 13:49    [12687664]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
Dmitry V. Liseev
Идея в том, что, поскольку в фильтрах в основном like и индексы бесполезны, если фильтровать не два раза а один, то скорость возрастет ровно вдвое. Что думаете по этому поводу?


а сколько собственно времени уходит на отдельное вычисление count(*) по фильтру без выборки полей?

но вообще, в свете новых сведений ("в фильтрах в основном like и индексы бесполезны") полагаю, что надо решать саму проблему долгой выборки, через полнотекстовый поиск или еще как-то. иначе с увеличением объемов данных все будет хуже и хуже
8 июн 12, 14:08    [12687869]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Shakill
а сколько собственно времени уходит на отдельное вычисление count(*) по фильтру без выборки полей?
Профайлер показывает, что практически столько же времени, как и с выборкой полей. И, судя по плану, основные затраты - именно фильтрация. Отсюда и возникла идея оптимизации.
8 июн 12, 14:15    [12687949]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
Dmitry V. Liseev,
попробуйте вариант с count(*) over() 12596652
8 июн 12, 14:37    [12688126]     Ответить | Цитировать Сообщить модератору
 Re: Как выбрать данные в одном запросе с количеством строк?  [new]
Dmitry V. Liseev
Member [заблокирован]

Откуда: Санкт-Петербург
Сообщений: 5489
Shakill
Dmitry V. Liseev,
попробуйте вариант с count(*) over() 12596652
Спасибо. То, что нужно. Я просто не силен в over, поскольку редко его использовал. Буду пробовать.
8 июн 12, 15:13    [12688482]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить