PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Hàm tổng hợp Postgres để tính trung bình vectơ của tốc độ gió (cường độ vectơ) và hướng gió (hướng vectơ)

Trước tiên, xin lỗi nếu tôi vi phạm bất kỳ quy tắc đăng bài nào ở đây, người đăng lần đầu tiên và tất cả những điều đó.

Tôi muốn sử dụng câu trả lời ở trên cùng với việc bổ sung thang đo thời gian cho postgres cho trạm thời tiết tự làm của tôi nhưng hóa ra chức năng này không song song an toàn. Ngoài ra, việc sử dụng atan không mang lại câu trả lời chính xác.

Vì vậy, đây là phiên bản đã sửa đổi của tôi mà tôi nghĩ nên an toàn song song và sử dụng atan2 để thay thế.

DROP AGGREGATE IF EXISTS vector_avg(float, float) CASCADE;
DROP TYPE IF EXISTS vector_sum CASCADE;
DROP TYPE IF EXISTS avg_vector CASCADE;

CREATE TYPE vector_sum AS (x float, y float, count int);
CREATE TYPE avg_vector AS (magnitude float, direction float);

CREATE OR REPLACE FUNCTION sum_vector (vectors vector_sum, magnitude float, direction float)
  RETURNS vector_sum LANGUAGE sql PARALLEL SAFE STRICT AS
'SELECT vectors.x + (magnitude * cos(radians(direction))), vectors.y + (magnitude * sin(radians(direction))), vectors.count + 1';

CREATE OR REPLACE FUNCTION combine_sum (part1 vector_sum , part2 vector_sum)
  RETURNS vector_sum LANGUAGE sql PARALLEL SAFE STRICT AS
'SELECT (part1.x+part2.x)/2,(part1.y+part2.y)/2,part1.count+part2.count';

CREATE OR REPLACE FUNCTION avg_vector_finalfunc(vectors vector_sum)
RETURNS avg_vector
AS
$$
DECLARE
        x float;
        y float;
        d float;
BEGIN
    BEGIN
        IF vectors.count = 0 THEN
            RETURN (NULL, NULL)::avg_vector;
        END IF;

        x := (vectors.x/vectors.count);
        y := (vectors.y/vectors.count);

        -- This means the vector is null vector
        -- Please see: https://math.stackexchange.com/a/3682/10842
        IF x = 0 OR y = 0 THEN
            RETURN (0, 0)::avg_vector;
        END IF;

         d:=degrees(atan2(y,x));

        -- atan2 returns negative result for angles > 180

        IF d < 0 THEN
          d := d+360;
        END IF;

        RETURN (sqrt(power(x, 2) + power(y, 2)), d )::avg_vector;
    EXCEPTION WHEN others THEN
        RETURN (NULL, NULL)::avg_vector;
    END;
END;
$$
LANGUAGE 'plpgsql'
PARALLEL SAFE
RETURNS NULL ON NULL INPUT;

CREATE AGGREGATE vector_avg (float, float) (
   sfunc     = sum_vector
 , stype     = vector_sum
 , combinefunc = combine_sum
 , finalfunc = avg_vector_finalfunc
 , initcond  = '(0.0, 0.0, 0)'
 , PARALLEL  = SAFE

Thử nghiệm từ một mẫu rất nhỏ:

psql -d weather -c "select * from windavgtest;"
             time              | direction | speed 
-------------------------------+-----------+-------
 2019-08-01 16:51:53.199357+00 |       170 |     1
 2019-08-01 16:51:54.388392+00 |       170 |     1
 2019-08-01 16:51:55.335034+00 |       170 |     1
 2019-08-01 16:51:56.362812+00 |       170 |     1
 2019-08-01 16:52:07.191919+00 |       190 |     1
 2019-08-01 16:52:08.250756+00 |       190 |     1
 2019-08-01 16:52:09.193265+00 |       190 |     1
 2019-08-01 16:52:10.224283+00 |       190 |     1
(8 rows)

sản lượng:

psql -d weather -c  "select round((vector_avg(speed, direction)).direction) AS wdirection from windavgtest;
"
 wdirection 
------------
        180
(1 row)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào tôi có thể viết một truy vấn SQL để tính toán số lượng các thành phần được bán với các hội đồng mẹ của chúng? (Postgres 11 / CTE đệ quy?)

  2. Django + PostgreSQL:tạo cơ sở dữ liệu (cấp đặc quyền gì)

  3. Postgresql trích xuất hàng cuối cùng cho mỗi id

  4. Quản lý tính khả dụng cao trong PostgreSQL - Phần II:Trình quản lý nhân bản

  5. Trả lại tất cả hồ sơ lịch sử cho các tài khoản có thay đổi về giá trị liên quan cụ thể