Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Построитель SQL-запросов  (Прочитано 29341 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
NeferSky
Постоялец

ua
Offline Offline
Бессмертный


« : 01-06-2017 13:50 » 

Добрый день.
Наставьте, пожалуйста, меня на путь истинный) Нужен мне построитель SQL-запросов для MSSQL, какой-нибудь, наверное. Или какой-то хитрый датасет. Или логику приложения перекроить совсем. Реализовать требуется вот что...
Есть грид, в который что-то там выбирается из базы:
Код:
select * from table1 t1
join table2 t2 on t2.t1_id = t1.id
join table3 t3 on t3.t2_id = t2.id
Фильтрацией этой выборки должны управлять два контрола для пользователей.
Один контрол берет на себя, в общем-то, всю where-часть запроса. То есть, вроде как, можно сляпать свой такой контрол, чтобы он возвращал часть where в виде строки, которая дописывается к запросу.
Второй контрол - простой "быстрый" фильтр, его, вроде как, можно навесить на датасет через свойство Filter.
И самое прекрасное: данные в гриде планируется представлять "страничками" по 50 записей. MSSQL умеет это делать в order-части запроса:
Код:
order by 1 offset ((:PAGE_NUM - 1)*50) rows fetch next 50 rows only
но... при этом "ломается" быстрый фильтр: получается так, что сначала выбирается 50 записей, а потом на них накладывается фильтр. Прописывать быстрый фильтр в where, мне думается, не очень хорошая идея, потому что им планируется пользоваться часто, и каждый раз датасет передергивать - накладно как-то. То есть, порядок действий пользователя планируется такой: наложил сложный фильтр (датасет передернул), получил некоторое небольшое количество записей, и уже по ним с быстрым фильтром перемещается как хочет... Т.к. записи в памяти все это время - должно получиться производительно. Хотя, пользователь может наложить и только один любой фильтр на все данные, если приспичит.
Вот и что с этим можно поделать?.. Может, шаблонные подходы какие-нибудь есть?
Записан

Не тронь налаженный механизм, и он тебя не подведет.
Делать надо хорошо, а плохо - само получится.
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #1 : 13-06-2017 05:28 » 

в дельфи не работаю, но
а у компонента DBGrid нет возможности постраничной выборки?
DBGrid paging
Записан

I Have Nine Lives You Have One Only
THINK!
NeferSky
Постоялец

ua
Offline Offline
Бессмертный


« Ответ #2 : 13-06-2017 12:30 » 

HandKot,
прошерстил сейчас интернет - да, этот кусок кода попадается на некоторых форумах... Но у TDBGrid нет такого свойства... У предков - тоже не обнаружено...
Записан

Не тронь налаженный механизм, и он тебя не подведет.
Делать надо хорошо, а плохо - само получится.
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #3 : 20-06-2017 07:52 » 

ну если нет возможности прикрутить данный грид, то как вариант использовать два датасета:
1 в первом основная выборка
2. во второй переносите данные после изменения "быстрой" фильтрации и/или смены страницы

второй уже и отображать в дата грид


больше пока на ум ничего не приходит
Записан

I Have Nine Lives You Have One Only
THINK!
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 20-06-2017 18:29 » 

О каком фильтре идет речь?

А разве нельзя выполнить запрос с пагинацией?

типа TOP
или
WHERE
RowNum >= :Offset
AND RowNum < :Offset + :Limit
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
NeferSky
Постоялец

ua
Offline Offline
Бессмертный


« Ответ #5 : 20-06-2017 18:56 » 

Sla, можно, но это будет что-то типа
Код:
(пример взят с stackoverflow)
SELECT  *
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, *
          FROM      Orders
          WHERE     OrderDate >= '1980-01-01'
        ) AS RowConstrainedResult
WHERE   RowNum >= 1
    AND RowNum < 20
ORDER BY RowNum
То есть, это "select from select". Мне кажется, это далеко не оптимальный запрос... По крайней мере, мне попадались рекомендации воздержаться от такого рода подзапросов.
Поэтому я и стараюсь выдумать что-то эдакое, чтобы одним запросом...
Записан

Не тронь налаженный механизм, и он тебя не подведет.
Делать надо хорошо, а плохо - само получится.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 20-06-2017 19:31 » 

Вы знаете другой способ пагинации?

для mysql limit offset

для оракла псевдостолбец ROWNUM

Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #7 : 21-06-2017 03:59 » 

О каком фильтре идет речь?

А разве нельзя выполнить запрос с пагинацией?

типа TOP
или
WHERE
RowNum >= :Offset
AND RowNum < :Offset + :Limit
1. насколько я понял тут проблема в "локальной" фильтрации (типа автофильтра в экселе)
Т.е сделали выборку, а потом на неё накладываются дополнительные ограничения.
Если доп.ограничения допиливать в запрос, плюс к ней постраничную выборку, а запрос выполняется долго (пусть пять минут) до переход с одной страницы на другую или же изменяя "локальный" фильтр, то пользователь скурится, ожидая ответа  Улыбаюсь  

2. Давно не работал с датасет. Нет там св-в "номер строки" и "фильтр". Если есть, то можно попробовать оттолкнутся от этого.


ЗЫЖ если вернутся к DBGrid или он платный ?
« Последнее редактирование: 21-06-2017 04:00 от HandKot » Записан

I Have Nine Lives You Have One Only
THINK!
NeferSky
Постоялец

ua
Offline Offline
Бессмертный


« Ответ #8 : 21-06-2017 09:01 » 

Sla, для MSSQL пагинация row_number() over, как в примере. Но с чем-то его сравнить можно только в вышестоящем запросе, также, как в примере. Но я именно что и хочу избавиться от вложенного select'а. Так что, или row_number() не подходит, или я недопонимаю, что Вы имеете в виду...

HandKot,
По 1:
> запрос выполняется долго (пусть пять минут) ... то пользователь скурится, ожидая ответа
Возможно... Вот и ищу варианты, как это сделать правильнее всего...
По 2:
> Давно не работал с датасет. Нет там св-в "номер строки" и "фильтр". Если есть, то можно попробовать оттолкнутся от этого.
Есть и то и другое. Немного не представляю, как привязаться к номеру строки в данном случае... А "фильтр" - пробовал, результат не тот, что хочу получить.
> если вернутся к DBGrid или он платный ?
Да он штатный Улыбаюсь

Попробую объяснить иными словами, что хочу реализовать:
Есть формочка с гридом. По умолчанию туда выбирается вся таблица из БД - пусть 100500 записей. Должна отображаться страничками по 50 записей.
Дальше - пользователь может наложить на это все сложный такой фильтр, типа, "Дата больше 01.01.2017 и (Сумма больше 100 и Сумма меньше 500)" - вернется, например, 50000 записей. Должно отображаться страничками по 50 записей.
Дальше - пользователь может наложить на это все быстрый фильтр, типа "Название начинается на 'АБВГД'" - допустим, вернется 100 записей. Должно отображаться страничками по 50 записей.
Пагинацию делаю с помощью "offset..." прямо в запросе. Так вот: при использовании свойства датасета "фильтр" этот "фильтр" наложится только на текущую страницу. А если на ней вообще нет названий начинающихся на 'АБВГД', то пользователь увидит пустой грид, хотя где-то в таблице подходящие записи могут существовать. То есть, фильтр сработает после пагинации.
Привязаться к свойству "номер строки" в данном случае интересная идея, но как это сделать? Если, как вариант, бросить туда еще один датасет, и в него перебрасывать записи из основного датасета? Не будет ли это слишком дорогим для ресурсов? Опять-таки, датасет чтобы работал, его надо Open(), а для этого нужно, чтобы в нем был select... Что-то какой-то велосипед я изобретаю.
Записан

Не тронь налаженный механизм, и он тебя не подведет.
Делать надо хорошо, а плохо - само получится.
HandKot
Молодой специалист

ru
Offline Offline

« Ответ #9 : 21-06-2017 10:20 » 

Цитата
Да он штатный Улыбаюсь
а в чём тогда проблема использования данного контрола?
Записан

I Have Nine Lives You Have One Only
THINK!
NeferSky
Постоялец

ua
Offline Offline
Бессмертный


« Ответ #10 : 21-06-2017 12:55 » 

Так эээ... У DBGrid'а мне не удалось обнаружить ничего дгя постраничного отображения.
Записан

Не тронь налаженный механизм, и он тебя не подведет.
Делать надо хорошо, а плохо - само получится.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 21-06-2017 16:57 » new

Сначала вы делаете
count отфильтрованного, прикидываете сколько у вас страниц

Затем TOP - таким образом вы получаете достаточно быстро первый сет

А уж при пагинации - пользуйте запросы для пагинации

Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines