Oracle
 sql >> база данни >  >> RDS >> Oracle

PostgreSQL еквивалент на функцията PERCENTILE_CONT на Oracle

След повече търсене намерих страница, която изброява псевдо-кода за това как Oracle прилага тази функция на:

http://docs.oracle.com/cd/B19306_01 /server.102/b14200/functions110.htm

Реших да напиша моя собствена функция в рамките на PG, за да имитирам функцията на Oracle.

Намерих техника за сортиране на масив от Дейвид Фетър в ::

http://postgres.cz/wiki/PostgreSQL_SQL_Tricks#General_array_sort

и

Сортиране на елементи от масив

Тук (за по-голяма яснота) е кодът на Дейвид:

CREATE OR REPLACE FUNCTION array_sort (ANYARRAY)
RETURNS ANYARRAY LANGUAGE SQL
AS $$
SELECT ARRAY(
    SELECT $1[s.i] AS "foo"
    FROM
        generate_series(array_lower($1,1), array_upper($1,1)) AS s(i)
    ORDER BY foo
);
$$;

И така, ето функцията, която написах:

CREATE OR REPLACE FUNCTION percentile_cont(myarray real[], percentile real)
RETURNS real AS
$$

DECLARE
  ary_cnt INTEGER;
  row_num real;
  crn real;
  frn real;
  calc_result real;
  new_array real[];
BEGIN
  ary_cnt = array_length(myarray,1);
  row_num = 1 + ( percentile * ( ary_cnt - 1 ));
  new_array = array_sort(myarray);

  crn = ceiling(row_num);
  frn = floor(row_num);

  if crn = frn and frn = row_num then
    calc_result = new_array[row_num];
  else
    calc_result = (crn - row_num) * new_array[frn] 
            + (row_num - frn) * new_array[crn];
  end if;

  RETURN calc_result;
END;
$$
  LANGUAGE 'plpgsql' IMMUTABLE;

Ето резултатите от някои сравнителни тестове:

CREATE TABLE testdata
(
  intcolumn bigint,
  fltcolumn real
);

Ето данните от теста:

insert into testdata(intcolumn, fltcolumn)  values  (5, 5.1345);
insert into testdata(intcolumn, fltcolumn)  values  (195, 195.1345);
insert into testdata(intcolumn, fltcolumn)  values  (1095, 1095.1345);
insert into testdata(intcolumn, fltcolumn)  values  (5995, 5995.1345);
insert into testdata(intcolumn, fltcolumn)  values  (15, 15.1345);
insert into testdata(intcolumn, fltcolumn)  values  (25, 25.1345);
insert into testdata(intcolumn, fltcolumn)  values  (495, 495.1345);
insert into testdata(intcolumn, fltcolumn)  values  (35, 35.1345);
insert into testdata(intcolumn, fltcolumn)  values  (695, 695.1345);
insert into testdata(intcolumn, fltcolumn)  values  (595, 595.1345);
insert into testdata(intcolumn, fltcolumn)  values  (35, 35.1345);
insert into testdata(intcolumn, fltcolumn)  values  (30195, 30195.1345);
insert into testdata(intcolumn, fltcolumn)  values  (165, 165.1345);
insert into testdata(intcolumn, fltcolumn)  values  (65, 65.1345);
insert into testdata(intcolumn, fltcolumn)  values  (955, 955.1345);
insert into testdata(intcolumn, fltcolumn)  values  (135, 135.1345);
insert into testdata(intcolumn, fltcolumn)  values  (19195, 19195.1345);
insert into testdata(intcolumn, fltcolumn)  values  (145, 145.1345);
insert into testdata(intcolumn, fltcolumn)  values  (85, 85.1345);
insert into testdata(intcolumn, fltcolumn)  values  (455, 455.1345);

Ето резултатите от сравнението:

ORACLE RESULTS
ORACLE RESULTS

select  percentile_cont(.25) within group (order by fltcolumn asc) myresult
from testdata;
select  percentile_cont(.75) within group (order by fltcolumn asc) myresult
from testdata;

myresult
- - - - - - - -
57.6345                

myresult
- - - - - - - -
760.1345               

POSTGRESQL RESULTS
POSTGRESQL RESULTS

select percentile_cont(array_agg(fltcolumn), 0.25) as myresult
from testdata;

select percentile_cont(array_agg(fltcolumn), 0.75) as myresult
from testdata;

myresult
real
57.6345

myresult
real
760.135

Надявам се това да помогне на някого, като не се налага да преоткрива колелото.

Насладете се! Рей Харис



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изтриване на таблица в Oracle SQL

  2. Предайте контролата към конкретен ред, като използвате командата Goto Label в PLSQL

  3. Oracle Order, като не работи за подзаявка от DUAL

  4. Извличане на данни за 31 декември от последните 5 години и днешната дата

  5. Функция TANH() в Oracle