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

लेटरल जॉइन में धीमे एग्रीगेट को ऑप्टिमाइज़ करें

यह LATERAL . के साथ एक तेज़ संस्करण होना चाहिए उपप्रश्न परीक्षण नहीं किया गया।

SELECT s.record_id, s.security_id, s.date
     , s.price / l.pmax   AS price_to_peak_earnings
     , s.price / l.pmin   AS price_to_minimum_earnings
  -- , ...
     , s.price / l.cape1  AS cape1
     , s.price / l.cape2  AS cape2
  -- , ...
     , s.price / l.cape10 AS cape10
     , s.price / l.capb1  AS capb1
     , s.price / l.capb2  AS capb2
  -- , ...
     , s.price / l.capb10 AS capb10
  -- , ...
FROM  (
   SELECT *
        , (date - interval  '1 y')::date AS date1
        , (date - interval  '2 y')::date AS date2
        -- ...
        , (date - interval '10 y')::date AS date10
   FROM  (
      SELECT *, min(date) OVER (PARTITION BY security_id) AS min_date
      FROM   security_data
      ) s1
   ) s
LEFT   JOIN LATERAL (
   SELECT CASE WHEN s.date10 >= s.min_date THEN NULLIF(max(earnings)                               , 0) END AS pmax
        , CASE WHEN s.date10 >= s.min_date THEN NULLIF(min(earnings)                               , 0) END AS pmin
        -- ...
        ,                                       NULLIF(avg(earnings) FILTER (WHERE date >= s.date1), 0)     AS cape1   -- no case
        , CASE WHEN s.date2  >= s.min_date THEN NULLIF(avg(earnings) FILTER (WHERE date >= s.date2), 0) END AS cape2
        -- ...
        , CASE WHEN s.date10 >= s.min_date THEN NULLIF(avg(earnings)                               , 0) END AS cape10  -- no filter

        ,                                       NULLIF(avg(book)     FILTER (WHERE date >= s.date1), 0)     AS capb1
        , CASE WHEN s.date2  >= s.min_date THEN NULLIF(avg(book)     FILTER (WHERE date >= s.date2), 0) END AS capb2
        -- ...
        , CASE WHEN s.date10 >= s.min_date THEN NULLIF(avg(book)                                   , 0) END AS capb10
        -- ...
   FROM   security_data 
   WHERE  security_id = s.security_id
   AND    date >= s.date10
   AND    date <  s.date
   ) l ON s.date1 >= s.min_date  -- no computations if < 1 year of trailing data
ORDER  BY s.security_id, s.date;

यह अभी भी बहुत तेज़ नहीं होने वाला है, क्योंकि प्रत्येक पंक्ति को कई अलग-अलग एकत्रीकरण की आवश्यकता होती है। यहां अड़चन सीपीयू होगी।

वैकल्पिक दृष्टिकोण के साथ अनुवर्ती कार्रवाई भी देखें (जेनरेट किए गए कैलेंडर + विंडो फ़ंक्शंस में शामिल हों):




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. पोस्टग्रेज सर्वर से कनेक्ट नहीं हो सका

  2. दूरस्थ पोस्टग्रेज सर्वर को pgAdmin के साथ एक्सेस करें

  3. plpgsql के अंदर \ set चर का उपयोग करें ब्लॉक घोषित करें

  4. थ्रेड सुरक्षित PQconn ऑब्जेक्ट

  5. डेल्टा ई (सीआईई लैब) का प्रदर्शन एसक्यूएल में गणना और छँटाई