Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > ADOQuery использование ф-и Rank


Автор: Vaskevych 14.2.2011, 23:26
Всем привет, подскажыте как можно использовать ф-ю rank в запросе к базе даных Access или ето нереально !!! Большое Списабо !!!


Примерный запрос:
Код

SELECT [rat_students].[familiastudenta] & " " & [rat_students].[namestudenta] & " " & [rat_students].[fstudenta] AS FIOStudenta, 
rat_students.Group, rat_1_2.*, rank() OVER ( [count_prog] ORDER BY count_prog)
FROM rat_students INNER JOIN rat_1_2 ON rat_students.Kod_Std = rat_1_2.Kod_Std WHERE rat_students.Group LIKE :Group
ORDER BY rat_students.FamiliaStudenta;


Автор: Данкинг 14.2.2011, 23:54
А что за функция такая?

Автор: Vaskevych 15.2.2011, 09:38
Ф-я которая отвечает за установку места относительно параметра, аналог РАНГ (RANK) в Excel.

Автор: Vas 15.2.2011, 09:50
Это же агрегатная функция, сомневаюсь что акцесс такое поддерживает. 
Vaskevych, у Тома Кайта подсмотрел?

Автор: Vaskevych 15.2.2011, 10:19
Ладно, если нет ф-ї буду писать сам, помогите !!!
Значит есть значения например:

зн.    Ранг

3      2      
7      4
7      4
2      1
6      3

Как я понимаю, сначала ищем минимальное значение (ето отправная точка).  min = 2, rank =1
Потом, ищем следующее min+1 если есть rank = 2 если нет ищем следующее.

как ето реализовать в Delphi покоректнее.

Автор: Vas 15.2.2011, 11:14
Цитата(Vaskevych @  15.2.2011,  10:19 Найти цитируемый пост)
Как я понимаю, сначала ищем минимальное значение (ето отправная точка).  min = 2, rank =1

А разве от сортировки ранг не зависит? Если в обратную сторону отсортировать то ранг 1 будет у максимального значения или я что-то путаю?

Добавлено через 2 минуты и 20 секунд
Вдогонку описание агрегатной функции rank в oracle

Автор: Vaskevych 15.2.2011, 20:26
Значит пишу свою ф-ю есть прогресс (потом выложу всем) только один вопрос можно ли в SQL запросе загнать значения какогото поля в массив. ?????

Автор: Vaskevych 17.2.2011, 21:19
Значит так как обещал, помогаю таким как я сам:  smile 

вот результат.
user posted image

1. Задаем поля Calculated для возможности вывода подсчетов.
2. В обаботчике CalcFields потомка ADOQuery (например) пишем код:

Код

var
  RecP: TRecord;
begin
  if DataSet.Bof then ado2tb.Clear;
  with RecP do
    begin
      UserID := DataSet.FieldByName('Auto_Index').AsInteger;
      UsValue:= DataSet.FieldByName('count_prog').AsInteger;
    end;
  ado2tb.AddRecord(RecP);

  DataSet.FieldByName('rank').AsInteger :=
  RankIndex(ado2tb, DataSet.FieldByName('count_prog').AsInteger);
end;


Что делает етот код ???
Он загоняет значения одного столбика в список с уникальным идентификатором (для возможности редактирования). 

RecP: TRecord Мой виртуальний список основан на TList (С понятных причин его не выбрасываю напишете сами):

Код

type
  TRecord = record
    UserID: integer;
    UsValue: integer;
  end;


3. В обработчике AfterOpen пишем код   ado2tb.Clear; - очищаем список от значений.
4. В обработчике AfterPost пишем код  

Код

var
  RecP: TRecord;
begin
  with RecP do
    begin
      UserID := DataSet.FieldByName('Auto_Index').AsInteger;
      UsValue:= DataSet.FieldByName('count_prog').AsInteger;
    end;
  ado2tb.AddRecord(RecP);

Изменяем значение которое редактировалось.

4. Сверху пишем 

Код

type
  TIntVec = array of Integer;


5. Сортируем масив методом пузырька (или другим)

Код

procedure BubbleSort(var a: TIntVec);
 var i,p,n: Integer; b: boolean;
begin
 n:= Length(a)-1;
 if n < 1 then exit;
 repeat
  b:= true;
  Dec(n);
  for i:= 0 to n do
   if a[i] > a[i+1] then
    begin
     p:= a[i];
     a[i]:= a[i+1];
     a[i+1]:= p;
     b:= false;
    end;
 until b;
end;


6. И вот сама функция которая отвечает за установку ранга

Код

function RankIndex(lst: TRecordList; ind: integer): integer;
var
  i,k,s: integer;
  mWin: TIntVec;
begin
  SetLength(mWin,lst.Count);

  for i := 0 to lst.Count-1 do
  begin
    mWin[i] := lst.Records[i].UsValue;
  end;

  BubbleSort(mWin);
   s := 0;
    for k := 0 to Length(mWin)-1 do
      begin
        if mWin[k] = mWin[k-1] then
          begin
            if ind = mWin[k] then
               s := s; 
          end
      else
        begin
         if ind = mWin[k] then
            s := k+1;
         end;
      end;
  Result := s;
end;


7. Все ...   smile  Если что то не ясно пишите в личку.

Автор: Vaskevych 18.2.2011, 21:41
Добавлю что для пересчета поля CalcFields используйте ф-ю ниже но предварительно проверте открыт ли компонент.

Код

Resync( [rmExact, rmCenter] );

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