PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

एक ही क्वेरी में दो मानों के बीच इंटरपोलेशन

यह एक बदसूरत हैक है (दुर्व्यवहार सीटीई पर आधारित;)। इसका सार यह है कि

value1 * distance2 + value2 * distance1

क्या, दूरी1*दूरी2 से विभाजित करके, इसे फिर से लिखा जा सकता है

value1/distance1 + value2/distance2

तो, उत्पाद (या डिवीजन) उनकी पंक्तियों के अंदर रह सकते हैं। योग के बाद, (distance1*distance2) से गुणा करने पर परिणाम वांछित आउटपुट में बदल जाता है। दो से अधिक पड़ोसियों के लिए सामान्यीकरण पाठक के लिए एक अभ्यास के रूप में छोड़ दिया गया है।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
    ;

परिणाम:

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

अपडेट करें:यह थोड़ा सा है क्लीनर ... संबंधों को अभी भी संभाला नहीं गया है (इसके लिए बाहरी क्वेरी में विंडो फ़ंक्शन या LIMIT 1 क्लॉज की आवश्यकता है)

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. PostgreSQL के लिए जॉब शेड्यूलिंग टूल्स का अवलोकन

  2. रेल 5.1 . में उचित नियंत्रक के लिए खोज प्रपत्र रूटिंग नहीं

  3. pgmemcache बनाम अनंत कैश

  4. फ़ंक्शन एकाधिक कॉलम के बजाय एकाधिक कॉलम को एक कॉलम के रूप में देता है

  5. PostgreSQL और लॉकिंग