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

प्रति पंक्ति अंतिम एन संबंधित पंक्तियों को क्वेरी करें

मान लें कि कम से कम 9.3 पोस्टग्रेज करता है।

सूचकांक

सबसे पहले, एक बहु-स्तंभ अनुक्रमणिका मदद करेगी:

CREATE INDEX observations_special_idx
ON observations(station_id, created_at DESC, id)

created_at DESC थोड़ा बेहतर फिट है, लेकिन सूचकांक अभी भी लगभग उसी गति से पीछे की ओर स्कैन किया जाएगा DESC के बिना ।

मान लें कि created_at परिभाषित किया गया है NOT NULL , अन्यथा DESC NULLS LAST consider पर विचार करें अनुक्रमणिका में और क्वेरी:

  • डेटाटाइम एएससी द्वारा पोस्टग्रेएसक्यूएल सॉर्ट करें, पहले शून्य?

अंतिम कॉलम id केवल तभी उपयोगी होता है जब आपको इसमें से केवल एक इंडेक्स स्कैन मिलता है, जो शायद काम नहीं करेगा यदि आप लगातार बहुत सारी नई पंक्तियाँ जोड़ते हैं। इस मामले में, id remove हटा दें सूचकांक से।

सरल क्वेरी (अभी भी धीमी)

अपनी क्वेरी को सरल बनाएं, आंतरिक उप-चयन मदद नहीं करता है:

SELECT id
FROM  (
  SELECT station_id, id, created_at
       , row_number() OVER (PARTITION BY station_id
                            ORDER BY created_at DESC) AS rn
  FROM   observations
  ) s
WHERE  rn <= #{n}  -- your limit here
ORDER  BY station_id, created_at DESC;

थोड़ा तेज़ होना चाहिए, लेकिन फिर भी धीमा होना चाहिए।

तेज़ क्वेरी

  • मान लें कि आपके पास अपेक्षाकृत कुछ है स्टेशन और अपेक्षाकृत अनेक प्रति स्टेशन अवलोकन।
  • station_id मानकर आईडी को NOT NULL as के रूप में परिभाषित किया गया है ।

वास्तव में . होना तेज़, आपको एक ढीले इंडेक्स स्कैन . के बराबर की आवश्यकता है (अभी तक पोस्टग्रेज में लागू नहीं किया गया है)। संबंधित उत्तर:

  • प्रति उपयोगकर्ता नवीनतम रिकॉर्ड पुनर्प्राप्त करने के लिए क्वेरी द्वारा GROUP ऑप्टिमाइज़ करें

यदि आपके पास stations . की एक अलग तालिका है (जिसकी संभावना प्रतीत होती है), आप इसका अनुकरण JOIN LATERAL . के साथ कर सकते हैं (9.3+ पोस्ट करें):

SELECT o.id
FROM   stations s
CROSS  JOIN LATERAL (
   SELECT o.id
   FROM   observations o
   WHERE  o.station_id = s.station_id  -- lateral reference
   ORDER  BY o.created_at DESC
   LIMIT  #{n}  -- your limit here
   ) o
ORDER  BY s.station_id, o.created_at DESC;

यदि आपके पास stations की तालिका नहीं है , अगली सबसे अच्छी बात एक को बनाना और बनाए रखना होगा। संभवतः संबंधपरक अखंडता को लागू करने के लिए एक विदेशी कुंजी संदर्भ जोड़ें।

यदि वह विकल्प नहीं है, तो आप मक्खी पर ऐसी तालिका को आसवन कर सकते हैं। आसान विकल्प होंगे:

SELECT DISTINCT station_id FROM observations;
SELECT station_id FROM observations GROUP BY 1;

लेकिन या तो अनुक्रमिक स्कैन की आवश्यकता होगी और धीमी गति से होना चाहिए। पोस्टग्रेज़ को उपरोक्त इंडेक्स (या station_id . के साथ किसी भी btree अनुक्रमणिका का उपयोग करें) प्रमुख कॉलम के रूप में) पुनरावर्ती CTE . के साथ :

WITH RECURSIVE stations AS (
   (                  -- extra pair of parentheses ...
   SELECT station_id
   FROM   observations
   ORDER  BY station_id
   LIMIT  1
   )                  -- ... is required!
   UNION ALL
   SELECT (SELECT o.station_id
           FROM   observations o
           WHERE  o.station_id > s.station_id
           ORDER  BY o.station_id
           LIMIT  1)
   FROM   stations s
   WHERE  s.station_id IS NOT NULL  -- serves as break condition
   )
SELECT station_id
FROM   stations
WHERE  station_id IS NOT NULL;      -- remove dangling row with NULL

इसका उपयोग ड्रॉप-इन प्रतिस्थापन . के रूप में करें stations . के लिए उपरोक्त सरल क्वेरी में तालिका:

WITH RECURSIVE stations AS (
   (
   SELECT station_id
   FROM   observations
   ORDER  BY station_id
   LIMIT  1
   )
   UNION ALL
   SELECT (SELECT o.station_id
           FROM   observations o
           WHERE  o.station_id > s.station_id
           ORDER  BY o.station_id
           LIMIT  1)
   FROM   stations s
   WHERE  s.station_id IS NOT NULL
   )
SELECT o.id
FROM   stations s
CROSS  JOIN LATERAL (
   SELECT o.id, o.created_at
   FROM   observations o
   WHERE  o.station_id = s.station_id
   ORDER  BY o.created_at DESC
   LIMIT  #{n}  -- your limit here
   ) o
WHERE  s.station_id IS NOT NULL
ORDER  BY s.station_id, o.created_at DESC;

परिमाण के क्रम . द्वारा यह अभी भी आपके पास जो था उससे तेज होना चाहिए ।

SQL Fiddle यहाँ (9.6)
db<>fiddle here



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle से PostgreSQL:ANSI बाहरी PostgreSQL में सिंटैक्स में शामिल हों

  2. जेपीए और हाइबरनेट के साथ पोस्टग्रेएसक्यूएल एनम को कैसे मैप करें?

  3. अद्वितीय डेटाटाइम सीमा के लिए पोस्टग्रेज बाधा

  4. भाषा बनाएं plpython3u - PostgreSQL 9.6

  5. कई तालिकाओं में से एक के लिए विदेशी कुंजी?