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

Nội suy giữa hai giá trị trong một truy vấn

Đây là một vụ hack xấu xí (dựa trên một CTE bị lạm dụng;). Điểm mấu chốt của nó là

value1 * distance2 + value2 * distance1

Có thể, bằng cách chia cho distance1 * distance2, được viết lại thành

value1/distance1 + value2/distance2

Vì vậy, các sản phẩm (hoặc bộ phận) có thể ở bên trong hàng của chúng. Sau khi tổng kết, nhân với (khoảng cách1 * khoảng cách2) sẽ thay đổi tỷ lệ kết quả thành đầu ra mong muốn. Tổng quát hóa cho nhiều hơn hai hàng xóm được để lại như một bài tập cho người đọc.YMMV

DROP TABLE tmp.points;
CREATE TABLE tmp.points
    ( pname VARCHAR NOT NULL PRIMARY KEY
    , distance INTEGER NOT NULL
    , value INTEGER
    );

INSERT INTO tmp.points(pname, distance, value) VALUES
  ( 'A' , 1, 10 )
,  ( 'B' , 4, 20 )
,  ( 'C' , 10 , 1)
,  ( 'D' , 11 , 2)
  ;
WITH RECURSIVE twin AS (
    select 1::INTEGER AS zrank
    , p0.pname AS zname
    , p0.distance AS dist
    , p0.value AS val
    , p0.distance* p0.value AS prod
    , p0.value::float / p0.distance AS frac
    FROM tmp.points p0
    WHERE NOT EXISTS ( SELECT * FROM tmp.points px
        WHERE px.distance < p0.distance)
    UNION
    select 1+twin.zrank AS zrank
    , p1.pname AS zname
    , p1.distance AS dist
    , p1.value AS val
    , p1.distance* p1.value AS prod
    , p1.value::float / p1.distance AS frac
    FROM tmp.points p1, twin
    WHERE p1.distance > twin.dist
    AND NOT EXISTS ( SELECT * FROM tmp.points px
        WHERE px.distance > twin.dist
        AND px.distance < p1.distance
        )   
    )
-- SELECT * from twin ;
SELECT min(zname) AS name1, max(zname) AS name2
    , MIN(dist) * max(dist) *SUM(frac) / SUM(dist) AS score
    FROM twin
    WHERE zrank <=2
    ;

Kết quả:

CREATE TABLE
INSERT 0 4
 name1 | name2 | score 
-------+-------+-------
 A     | B     |    12

Cập nhật:cái này là một chút dọn dẹp ... mối quan hệ vẫn không được xử lý (cần một hàm cửa sổ hoặc một mệnh đề LIMIT 1 trong truy vấn bên ngoài cho điều đó)

WITH RECURSIVE twin AS (
    select 1::INTEGER AS zrank
    , p0.pname AS name1
    , p0.pname AS name2
    , p0.distance AS dist
    FROM tmp.points p0
    WHERE NOT EXISTS ( SELECT * FROM tmp.points px
        WHERE px.distance < p0.distance)
    UNION
    select 1+twin.zrank AS zrank
    , twin.name1 AS name1
    , p1.pname AS name2
    , p1.distance AS dist
    FROM tmp.points p1, twin
    WHERE p1.distance > twin.dist
    AND NOT EXISTS ( SELECT * FROM tmp.points px
        WHERE px.distance > twin.dist
        AND px.distance < p1.distance
        )
    )
SELECT twin.name1, twin.name2
    , (p1.distance * p2.value + p2.distance * p1.value) / (p1.distance+p2.distance)  AS score
    FROM twin
    JOIN tmp.points p1 ON (p1.pname = twin.name1)
    JOIN tmp.points p2 ON (p2.pname = twin.name2)
    WHERE twin.zrank =2
    ;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bảng dưới dạng đối số của một hàm PostgreSQL

  2. Cách tính toán phần trăm trong PostgreSQL

  3. Cách tìm tất cả các hàng có giá trị NULL trong bất kỳ cột nào bằng PostgreSQL

  4. Tạo người dùng PostgreSQL và thêm họ vào cơ sở dữ liệu

  5. Chỉ trả về các giá trị số từ một cột cơ sở dữ liệu PostgreSQL