현재 레코드로 일련의 작업을 수행 한 다음 결과를 반환하는 PostgreSQL 함수

xplorer

PostgreSQL 함수와 저장 프로 시저에 익숙하지 않지만 지난 며칠 동안 배우기 위해 최선을 다했습니다. 여기서 물어보기 전에 열심히 노력했습니다.

기본적으로 간단한 SQL을 사용할 수없고 함수가 가장 도움 이되는 상황 이 있습니다. (이는 AJAX를 통해 JSONP를 반환하는 Postgres 기반 웹 서비스로 쿼리를 보내고 있기 때문이며 쿼리가 미리 결정되지 않은 수의 변수를 기반으로 JavaScript로 빌드 되었기 때문에 2000 개 정도의 URL 문자를 넘어서 성장할 수 있습니다. MSIE에서 허용되는 제한.)

클라이언트 라는 테이블이 있습니다 .

+-------------+-------------------+-------------+---------------+
|   CLIENT    | MONTHLY_PURCHASES | SALES_VALUE | RETURNS_VALUE |
+-------------+-------------------+-------------+---------------+
| Mercury Ltd | 3                 | 400000      | 30000         |
| Saturn Plc  | 11                | 150000      | 30000         |
| Uranus Ltd  | 4                 | 80000       | 1000          |
+-------------+-------------------+-------------+---------------+

쿼리는 열에 포함 된 다양한 기준에 따라 순위가 매겨진 클라이언트를 반환해야합니다. 열 수는 향후 증가 할 수 있습니다.

예를 들어 100 (최고)에서 0 (최악)으로 순위가 매겨진 상위 10 개의 최고 클라이언트를 얻으려면 SQL 쿼리는 다음과 같습니다.

WITH var AS (
    --we need the min and max values for each criteria, to calculate the rank later
    SELECT 
      MIN(monthly_purchases) AS min_pur,
      MAX(monthly_purchases) AS max_pur,
      MIN(sales_value) AS min_sales,
      MAX(sales_value) AS max_sales,
      MIN(returns_value) AS min_returns,
      MAX(returns_value) AS max_returns
    FROM clients
),
--standardise values to a 0 to 100 range, so we can compare apples with oranges, and assign weights to each criteria (from 0 to 1)
weights AS (        
    SELECT client,
      --the higher the number of purchases the better. Weight: 0.2 out of 1.
      0.2 * (clients.monthly_purchases - var.min_pur) / (var.max_pur - var.min_pur) * 100 AS rnk_pur,
      --the higher the value of sales, the better. Weight: 0.4 out of 1.
      0.4 * (clients.sales_value - var.min_sales) / (var.max_sales - var.min_sales) * 100 AS rnk_sales,
      --the lower the value of returns the better. Weight: 0.4 out of 1.
      0.4 * (1 - (clients.returns_value - var.min_returns) / (var.max_returns - var.min_returns)) * 100 AS rnk_returns
    FROM clients, var
)
SELECT weights.client, weights.rnk_pur + weights.rnk_sales + weights.rnk_returns as overall_rank FROM weights ORDER BY overall_rank DESC LIMIT 10

모든 것이 좋지만 실제로는 열 수가 더 많고 (약 40 개) 사용자는 순위를 매기기 위해 1에서 15 사이의 항목을 한 번에 사용할 수 있습니다.

따라서 SQL 경로는 실행 가능하지 않습니다. 적어도 값의 표준화를 수행 할 함수를 만들려고했습니다.

--Firstly, a function to find the highest value in an array
DROP FUNCTION IF EXISTS array_max(float[]);

CREATE OR REPLACE FUNCTION array_max(float[])
RETURNS float
AS $$
  select max(x) from unnest($1)x order by 1;
$$
LANGUAGE 'sql';

--Secondly, a function to find the lowest value in an array
DROP FUNCTION IF EXISTS array_min(float[]);

CREATE OR REPLACE FUNCTION array_min(float[])
RETURNS float
AS $$
  select min(x) from unnest($1)x order by 1;
$$
LANGUAGE 'sql';

--Finally, our function
DROP FUNCTION IF EXISTS standardise(float[], float);

CREATE OR REPLACE FUNCTION standardise(myarray float[], val float)
RETURNS float AS
$$

DECLARE
  minimum float;
  maximum float;
  calc_result float;
BEGIN
  minimum = array_min(myarray);
  maximum = array_max(myarray);

  calc_result = (val - minimum) / (maximum - minimum) * 100;

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

당연히이 기능은 상당히 느립니다. 다음과 같이 사용하는 경우 :

SELECT 0.5 * standardise ((SELECT array (SELECT sales_value FROM clients)), clients.sales_value) AS rnk_sales 
FROM clients

... 허용됩니다. 주문과 관련된 모든 것은 크롤링 속도를 늦 춥니 다. 즉 :

SELECT 0.5 * standardise ((SELECT array (SELECT sales_value FROM clients)), clients.sales_value) AS rnk_sales 
FROM clients ORDER BY rnk_sales LIMIT 10

위 기능의 속도를 향상시킬 수있는 방법이 있습니까? 아니면 완전히 다른 접근 방식일까요? 어떤 도움이라도 대단히 감사하겠습니다. 감사!

최신 정보:

마지막 쿼리로 EXPLAIN ANALYZE를 실행했습니다. 이를 위해 너무 오래 걸리기 때문에 전체 테이블에서 샘플 만 선택했습니다. 10 분을 기다린 후 쿼리를 취소했습니다. 이것은 1000 개의 클라이언트가있는 테이블에 있습니다.

EXPLAIN ANALYZE SELECT 0.5 * standardise ((SELECT array (SELECT sales_value FROM clients_sample)), clients_sample.sales_value) AS rnk_sales 
FROM clients_sample ORDER BY rnk_sales LIMIT 10

결과:

제한 (비용 = 78.82..78.83 행 = 10 너비 = 8) (실제 시간 = 357.806..357.822 행 = 10 루프 = 1) 
  InitPlan 2 ($ 1 반환) 
    -> 결과 (비용 = 12.00..12.00 행 = 1 너비 = 0) (실제 시간 = 1.267..1.268 행 = 1 루프 = 1) 
          InitPlan 1 ($ 0 반환) 
            -> clients_sample clients_sample_1에 대한 Seq Scan (비용 = 0.00..12.00 행 = 1000 너비 = 8) (실제 시간 = 0.002 ..0.666 rows = 1000 loops = 1) 
  -> Sort (cost = 66.82..67.32 rows = 1000 width = 8) (실제 시간 = 357.805..357.809 rows = 10 loops = 1) 
        Sort Key : ((0.5 :: 배정 밀도 * standardise ($ 1, clients_sample.sales_value))) 
        정렬 방법 : 상위 N 힙 정렬 메모리 : 25kB
        -> clients_sample에서 Seq Scan (비용 = 0.00..62.50 행 = 1000 너비 = 8) (실제 시간 = 1.870..356.742 행 = 1000 루프 = 1) 
총 런타임 : 357.850ms
Erwin Brandstetter

위생 화 된 도우미 기능

CREATE OR REPLACE FUNCTION array_max(float[])
  RETURNS float AS
'SELECT max(x) from unnest($1) x'
LANGUAGE sql;

ORDER BY 1max(x)어쨌든 단일 행을 반환하기 때문에 쓸모가 없습니다 .
동일 array_min(float[]);

그러나 이러한 기능을 사용 하지 마십시오 . 얻을 저렴 min()하고 max()하나의 호출.

주요 기능:

대신 간단한 SQL 함수를 사용하십시오.

CREATE OR REPLACE FUNCTION standardise(_arr float[], _val float)
  RETURNS float AS
$func$
SELECT ((_val - min_x) * 100) / (max_x - min_x)
FROM (
   SELECT min(x) AS min_x, max(x) AS max_x
   FROM   unnest($1) x
   ) sub
$func$
LANGUAGE sql IMMUTABLE;
  • 하위 쿼리를 사용하여 한 번에 두 집계를 가져옵니다.
  • 일반적으로 더 높은 정밀도를 위해 먼저 곱하십시오.
  • 언어 이름을 인용하지 마십시오.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

R의 glht 함수는 수작업으로 수행 한 계산과 다른 결과를 제공합니다.

분류에서Dev

레코드를 삽입하는 PostgreSQL 함수가 의도 한대로 작동하지 않습니다.

분류에서Dev

둘 다 동일한 수의 지정된 문자를 포함하는 경우 행을 다음 행과 연결

분류에서Dev

JavaScript : 함수는 콜백 함수의 결과를 기반으로 재정렬 된 배열을 반환합니다.

분류에서Dev

함수로 레코드를 변경 한 다음 새 레코드를 업데이트하는 F # 구문

분류에서Dev

PostgreSql : 함수는 레코드를 반환합니다. filed 중 하나는 int 또는 bool 일 수 있습니다.

분류에서Dev

함수 포인터를 void 함수로 캐스팅 한 다음 호출하여 반환 값을 "쓰레기"하는 정의되지 않은 동작입니까?

분류에서Dev

VBA 레코드 세트 액세스-다른 필드를 입력으로 사용하는 함수의 결과를 기반으로 필드 업데이트

분류에서Dev

한 번에 하나의 디스패치 작업을 수행하고 새로 시작할 때 현재 작업을 취소합니다.

분류에서Dev

함수를 받고 스레드에 대한 핸들을 반환하는 다른 함수를 반환하는 함수의 형식 서명은 무엇입니까?

분류에서Dev

Openmp의 감소는 내 코드에서 동일한 수의 스레드로 다른 결과를 반환합니다.

분류에서Dev

PostgreSQL 함수는 모든 레코드를 반환합니다.

분류에서Dev

postgresql : 함수가 반환 한 단일 행을 테이블에 결합하는 방법

분류에서Dev

Oracle에서 다른 결과를 반환하는 동일한 함수

분류에서Dev

함수에서 libusb :: Device 반환 문제-현재 함수가 소유 한 데이터를 참조하는 값을 반환하려고합니다.

분류에서Dev

정수 목록이 있습니다. 목록 항목에 대해 몇 가지 작업을 수행 한 다음 결과를 파일로 인쇄합니다.

분류에서Dev

작업 결과를 함수로 반환

분류에서Dev

전용 서버에서 NonDedicatedServer로 Csv 파일을 업로드 한 후 다음 작업을 수행하는 방법

분류에서Dev

현재 행에있는 다른 열의 매개 변수를 기반으로 한 표현식에서 값이 다른 모든 행의 열 업데이트

분류에서Dev

max 함수 (excel)에서 반환 된 동일한 행의 다른 셀 값을 결정하기위한 셀 함수

분류에서Dev

여러 행을 결합한 각 레코드에 대해 가변 개수의 열을 반환하는 SQL 쿼리

분류에서Dev

동일한 인수로 동일한 함수를 10 번 실행하고 결과를 얻습니다.

분류에서Dev

재귀 함수의 최종 결과에 대해 동일한 기능을 수행하면서 수행

분류에서Dev

Promise.all ()을 반환 한 다음 함수로 반환하는 방법

분류에서Dev

함수를 작성하는 방법은 replace ()와 동일한 작업을 수행합니다.

분류에서Dev

HeidiSQL로 만든 postgresql 함수가 결과를 반환하지 않습니다.

분류에서Dev

일치하는 2 개의 코호트와 관련하여 하위 클래스를 기반으로 재구성 한 다음 연속 McNemar 테스트를 수행합니다.

분류에서Dev

Postgresql 일련의 일일 레코드 수

분류에서Dev

Haskell 프로그래밍에서 두 개의 함수 목록을 번갈아 결합한 결과 함수를 반환하는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    R의 glht 함수는 수작업으로 수행 한 계산과 다른 결과를 제공합니다.

  2. 2

    레코드를 삽입하는 PostgreSQL 함수가 의도 한대로 작동하지 않습니다.

  3. 3

    둘 다 동일한 수의 지정된 문자를 포함하는 경우 행을 다음 행과 연결

  4. 4

    JavaScript : 함수는 콜백 함수의 결과를 기반으로 재정렬 된 배열을 반환합니다.

  5. 5

    함수로 레코드를 변경 한 다음 새 레코드를 업데이트하는 F # 구문

  6. 6

    PostgreSql : 함수는 레코드를 반환합니다. filed 중 하나는 int 또는 bool 일 수 있습니다.

  7. 7

    함수 포인터를 void 함수로 캐스팅 한 다음 호출하여 반환 값을 "쓰레기"하는 정의되지 않은 동작입니까?

  8. 8

    VBA 레코드 세트 액세스-다른 필드를 입력으로 사용하는 함수의 결과를 기반으로 필드 업데이트

  9. 9

    한 번에 하나의 디스패치 작업을 수행하고 새로 시작할 때 현재 작업을 취소합니다.

  10. 10

    함수를 받고 스레드에 대한 핸들을 반환하는 다른 함수를 반환하는 함수의 형식 서명은 무엇입니까?

  11. 11

    Openmp의 감소는 내 코드에서 동일한 수의 스레드로 다른 결과를 반환합니다.

  12. 12

    PostgreSQL 함수는 모든 레코드를 반환합니다.

  13. 13

    postgresql : 함수가 반환 한 단일 행을 테이블에 결합하는 방법

  14. 14

    Oracle에서 다른 결과를 반환하는 동일한 함수

  15. 15

    함수에서 libusb :: Device 반환 문제-현재 함수가 소유 한 데이터를 참조하는 값을 반환하려고합니다.

  16. 16

    정수 목록이 있습니다. 목록 항목에 대해 몇 가지 작업을 수행 한 다음 결과를 파일로 인쇄합니다.

  17. 17

    작업 결과를 함수로 반환

  18. 18

    전용 서버에서 NonDedicatedServer로 Csv 파일을 업로드 한 후 다음 작업을 수행하는 방법

  19. 19

    현재 행에있는 다른 열의 매개 변수를 기반으로 한 표현식에서 값이 다른 모든 행의 열 업데이트

  20. 20

    max 함수 (excel)에서 반환 된 동일한 행의 다른 셀 값을 결정하기위한 셀 함수

  21. 21

    여러 행을 결합한 각 레코드에 대해 가변 개수의 열을 반환하는 SQL 쿼리

  22. 22

    동일한 인수로 동일한 함수를 10 번 실행하고 결과를 얻습니다.

  23. 23

    재귀 함수의 최종 결과에 대해 동일한 기능을 수행하면서 수행

  24. 24

    Promise.all ()을 반환 한 다음 함수로 반환하는 방법

  25. 25

    함수를 작성하는 방법은 replace ()와 동일한 작업을 수행합니다.

  26. 26

    HeidiSQL로 만든 postgresql 함수가 결과를 반환하지 않습니다.

  27. 27

    일치하는 2 개의 코호트와 관련하여 하위 클래스를 기반으로 재구성 한 다음 연속 McNemar 테스트를 수행합니다.

  28. 28

    Postgresql 일련의 일일 레코드 수

  29. 29

    Haskell 프로그래밍에서 두 개의 함수 목록을 번갈아 결합한 결과 함수를 반환하는 방법은 무엇입니까?

뜨겁다태그

보관