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

SQL क्वेरी को प्रोग्रामेटिक रूप से बनाने के लिए मजबूत दृष्टिकोण

बेहतर क्वेरी

शुरुआत के लिए आप वाक्य रचना को ठीक कर सकते हैं, सरल बना सकते हैं और थोड़ा स्पष्ट कर सकते हैं:

SELECT *
FROM  (
   SELECT p.person_id, p.name, p.team, sum(s.score)::int AS score
         ,rank() OVER (PARTITION BY p.team
                       ORDER BY sum(s.score) DESC)::int AS rnk
    FROM  person p
    JOIN  score  s USING (person_id)
    GROUP BY 1
   ) sub
WHERE  rnk < 3;
  • मेरे अद्यतन तालिका लेआउट पर निर्माण। नीचे बेला देखें।

  • आपको अतिरिक्त सबक्वायरी की आवश्यकता नहीं है। विंडो फ़ंक्शन बाद निष्पादित किए जाते हैं समग्र कार्य, ताकि आप इसे प्रदर्शित की तरह घोंसला बना सकें।

  • "रैंक" के बारे में बात करते समय, आप शायद रैंक () . का उपयोग करना चाहते हैं , नहीं row_number()

  • मान लें कि people.people_id PK है, आप GROUP BY को सरल बना सकते हैं ।

  • सभी कॉलम नामों को तालिका-योग्य बनाना सुनिश्चित करें जो अस्पष्ट हो सकते हैं

PL/pgSQL फ़ंक्शन

तब मैं एक plpgsql फ़ंक्शन लिखूंगा जो आपके चर भागों के लिए पैरामीटर लेता है। a को लागू करना - सी आपके अंक का। डी अस्पष्ट है, इसे आपके ऊपर जोड़ने के लिए छोड़ दिया गया है।

CREATE OR REPLACE FUNCTION f_demo(_agg text       DEFAULT 'sum'
                               , _left_join bool  DEFAULT FALSE
                               , _where_name text DEFAULT NULL)
  RETURNS TABLE(person_id int, name text, team text, score int, rnk int) AS
$func$
DECLARE
   _agg_op  CONSTANT text[] := '{count, sum, avg}';  -- allowed functions
   _sql     text;
BEGIN

-- assert --
IF _agg ILIKE ANY (_agg_op) THEN
   -- all good
ELSE
   RAISE EXCEPTION '_agg must be one of %', _agg_op;
END IF;

-- query --
_sql := format('
SELECT *
FROM  (
   SELECT p.person_id, p.name, p.team, %1$s(s.score)::int AS score
         ,rank() OVER (PARTITION BY p.team
                       ORDER BY %1$s(s.score) DESC)::int AS rnk
    FROM  person p
    %2$s  score  s USING (person_id)
    %3$s
    GROUP BY 1
   ) sub
WHERE  rnk < 3
ORDER  BY team, rnk'
   , _agg
   , CASE WHEN _left_join THEN 'LEFT JOIN' ELSE 'JOIN' END
   , CASE WHEN _where_name <> '' THEN 'WHERE p.name LIKE $1' ELSE '' END
);

-- debug   -- quote when tested ok
-- RAISE NOTICE '%', _sql;

-- execute -- unquote when tested ok
RETURN QUERY EXECUTE _sql
USING  _where_name;   -- $1

END
$func$  LANGUAGE plpgsql;

कॉल करें:

SELECT * FROM f_demo();
SELECT * FROM f_demo('sum', TRUE, '%2');    
SELECT * FROM f_demo('avg', FALSE);
SELECT * FROM f_demo(_where_name := '%1_'); -- named param

SQL Fiddle




  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. PostgreSQL में कॉलम के रूप में पंक्ति मानों का उपयोग करें

  3. Microsoft Azure पर PostgreSQL के लिए फ़ेलओवर और फ़ेलबैक

  4. बहुरूपी प्रकार का निर्धारण नहीं कर सका क्योंकि इनपुट का प्रकार अज्ञात है

  5. पोस्टग्रेज अनुपात_to_report फ़ंक्शन