Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Firebird, Interbase > select top 50 percent


Автор: tishaishii 7.7.2011, 10:01
Как выполнить запрос: 
Код
select top 50 percent id from t1
 ?

Автор: FMA 7.7.2011, 12:06
Код

select first 50 id from t1

не подойдет?

Автор: tishaishii 9.7.2011, 09:54
В MSACCESS, по-моему, наряду с возможностью указания абсолютной мощности выборки, есть возможность указать относительную.
"50 percent" - это половина.

Автор: Akella 9.7.2011, 20:56
Подойдёт ли так?
Код

execute BLOCK RETURNS (id integer)
as
DECLARE VARIABLE a INTEGER;
DECLARE VARIABLE b INTEGER;
begin
  select count(id) id from apart into :a;
  b = a/2;

  for select first (:b) id from apart into :id
  do
  SUSPEND;
end


По другому не знаю как :(, попробуй задай вопрос на SQL.RU

Добавлено через 1 минуту и 55 секунд
С входящим параметром

Код

execute BLOCK (p1 integer = :p1)
RETURNS (id integer)
as
DECLARE VARIABLE a INTEGER;
DECLARE VARIABLE b INTEGER;
begin
  select count(id) id from apart into :a;
  b = a/p1;

  for select first (:b) id from apart into :id
  do
  SUSPEND;
end

Автор: tishaishii 14.7.2011, 22:02
Есть много запросов, в них много разных связанных отношений и условий. Нет желания описывать каждый запрос в качестве блока или процедуры. Хотелось сократить код и не использовать составление запроса "на лету".

Автор: password 14.7.2011, 22:11
А нельзя упростить так:
Код

select first ((select count(*) from t1)*0.5) id from  t1

Автор: tishaishii 14.8.2011, 08:57
Не подойдёт.
В задаче есть много (около 1000) разных запросов, которые часто изменяются (выгрузка информации для справочного печатного издания).
Хочется как-то упростить их.

Сейчас, у меня это делается с помощью парсера. Строка вида
Код

0.5       t1 as t11 inner join t2 on ....... inner join t1 as t12 on ......... where .......... order by .....


разбивается и выполняются два запроса с ?COUNT=count(*) и ?PERCENT=0.5.
Т.е.

Код
select count(*) as "COUNT" from t1 as t11 inner join t2 on ....... inner join t1 as t12 on ......... where .......... into ?"COUNT";
select first (?"COUNT" * ?"PERCENT") * from t1 as t11 inner join t2 on ....... inner join t1 as t12 on ......... where .......... order by .....


Может быть, можно внутри SQL перед работой с курсором узнать сколько строк удастся выбрать? row_count что-то молчит.

Автор: rodnover 14.8.2011, 20:41
Не знаю, на сколько будет оптимизированно, но возможно, набор данных будет вычислять один раз, если сделать через 2 SP

Код

create or alter procedure QUERY_TABLES -- Требуется для нумерации строчек
returns(ID_ROW_NUM integer,
   ...)
declare ROW_NUM integer;
as
begin
    ROW_NUM = 1;
    for
        select :ROW_NUM, *
        from NEEDED_TABLES
        -- Сортировать в обратном нужному порядке
        into :ID_ROW_NUM, ....
    do
    begin
        suspend;
       ROW_NUM = :ROW_NUM + 1;
    end
end


Код

execute block
returns(...)
declare MAX_ROW integer;
as
begin
    MAX_ROW = null;
    for
        select *
        from QUERY_TABLES
        order by ID_ROW_NUM desc -- Начинаем с самой большой строки, содержит общее количество строк
        into :ID_ROW_NUM, .....
    do
    begin
         if MAX_ROW is null then
               MAX_ROW = ID_ROW_NUM / 2; -- Получаем ровно половину строк
         else if ID_ROW_NUM >= MAX_ROW then -- Выводим только большую первую половину
              suspend;
        else
             break;
    end
end


Завтра на работе попробую потестировать на больших данных. smile

Автор: tishaishii 14.8.2011, 22:05
Спасибо за желание помочь, rodnover!
Думаю, всё-таки, сохранение каждого (из 1000-2000) отношения в БД - это нормальная практика.
Есть небольшой недостаток: при редактировании шаблона выгрузки, придётся дополнительно пересоздавать соответствующее отношение в БД. Возможно, в связи с этим, стоит подумать как описать в БД и сами шаблоны.

Для ясности. Для публикации информации из БД используется простой шаблонизатор с множеством блоков (1000-2000, "по погоде") вида:
Код
ЗАГОЛОВОК

ТЕЛО

ЗАПРОС


Моим вариантом решения будет для каждого запроса создавать процедуру (for ЗАПРОС into ... do suspend) с именем вида "PUB_{sha1_hex(ЗАПРОС)}".
Вопрос открыт.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)