2012-07-13 20 views
12

में क्रॉस लागू करने के लिए पोस्टग्रेज़ एनालॉग मुझे एमएस एसक्यूएल सर्वर 2005 के लिए पोस्ट किए गए एसक्यूएल प्रश्नों को माइग्रेट करने की आवश्यकता है 9.1।
इस क्वेरी में CROSS APPLY के लिए विकल्प का सबसे अच्छा तरीका क्या है?एसक्यूएल सर्वर

SELECT * 
FROM V_CitizenVersions   
CROSS APPLY  
     dbo.GetCitizenRecModified(Citizen, LastName, FirstName, MiddleName, 
BirthYear, BirthMonth, BirthDay, .....) -- lots of params 

GetCitizenRecModified() फ़ंक्शन एक तालिका मूल्यवान फ़ंक्शन है। मैं इस फ़ंक्शन का कोड नहीं डाल सकता क्योंकि यह वास्तव में बहुत बड़ा है, यह कुछ कठिन कंप्यूटेशंस बनाता है और मैं इसे छोड़ नहीं सकता।

+0

आप क्रॉस Postgres में लागू की जरूरत नहीं है। आप फ़ंक्शन की तरह एक टेबल फ़ंक्शन का उपयोग कर सकते हैं। बस उनसे जुड़ें। –

+0

@a_horse_with_no_name - 'क्रॉस आवेदन 'टीवीएफ को एक बार निष्पादित करने के बजाय सहसंबंधित पैरामीटर के साथ फिर से निष्पादित करता है और फिर परिणाम में शामिल होता है। –

उत्तर

8

Postgres में 9.3 या बाद में एक LATERAL में शामिल होने का उपयोग करें?


पुराने संस्करणों के लिए, वहाँ पूरा करने के लिए क्या मुझे लगता है कि आप एक सेट लौटने समारोह (RETURNS TABLE or RETURNS SETOF record OR RETURNS record) के साथ की कोशिश कर रहे एक बहुत ही सरल तरीका है:

SELECT *, (f_citizen_rec_modified(col1, col2)).* 
FROM v_citizenversions v 

फ़ंक्शन मानों की गणना करता है o बाहरी क्वेरी की हर पंक्ति के लिए एनसीई। यदि फ़ंक्शन एकाधिक पंक्तियां देता है, जिसके परिणामस्वरूप पंक्तियों को तदनुसार गुणा किया जाता है। पंक्तियों को विघटित करने के लिए सभी कोष्ठक को को वाक्य रचनात्मक रूप से आवश्यक है। तालिका समारोह कुछ इस तरह दिखाई दे सकता है:

CREATE OR REPLACE FUNCTION f_citizen_rec_modified(_col1 int, _col2 text) 
    RETURNS TABLE(col_c integer, col_d text) AS 
$func$ 
SELECT s.col_c, s.col_d 
FROM some_tbl s 
WHERE s.col_a = $1 
AND s.col_b = $2 
$func$ LANGUAGE sql; 

आप एक सबक्वेरी या CTE में इस रैप करने के लिए की जरूरत है अगर आप एक WHERE खंड लागू करने के लिए, क्योंकि कॉलम एक ही स्तर पर दिखाई नहीं देते हैं चाहता हूँ। (और यह वैसे भी प्रदर्शन के लिए बेहतर है, क्योंकि आप समारोह के हर उत्पादन स्तंभ के लिए मूल्यांकन दोहराया रोकने):

SELECT col_a, col_b, (f_row).* 
FROM (
    SELECT col_a, col_b, f_citizen_rec_modified(col1, col2) AS f_row 
    FROM v_citizenversions v 
    ) x 
WHERE (f_row).col_c = _col_c; 

इस या इसी तरह कुछ करने के लिए कई अन्य तरीके हैं। यह सब वास्तव में आप जो चाहते हैं उस पर निर्भर करता है।

+0

मैंने आपके द्वारा प्रस्तावित क्वेरी का उपयोग किया था। अब मैं चौंक गया हूं: क्वेरी एक मिनट से अधिक निष्पादित करती है। एमएस एसक्यूएल में यह एक दूसरे ओ_ओ से कम लेता है। – user1178399

+1

@ user1178399: खेल में कई कारकों को जानने के बिना उस पर टिप्पणी करना व्यावहारिक रूप से असंभव है। मैं अनुमान लगाता हूं कि प्रदर्शन में सुधार किया जा सकता है। –

1

यह लिंक कैसे Postgres में 9.0+ यह करने के लिए दिखाने के लिए प्रकट होता है:

PostgreSQL: parameterizing a recursive CTE

यह "नकल क्रॉस सेट लौटने कार्यों के साथ लागू करें" शीर्षक वाले भाग में पृष्ठ में और नीचे है। उदाहरण के बाद सीमाओं की सूची नोट करना सुनिश्चित करें।

SELECT v.col_a, v.col_b, f.* -- no parentheses here, f is a table alias 
FROM v_citizenversions v 
LEFT JOIN LATERAL f_citizen_rec_modified(v.col1, v.col2) f ON true 
WHERE f.col_c = _col_c; 

क्यों LEFT JOIN LATERAL ... ON true:

1

मुझे पसंद इरविन Brandstetter का जवाब हालांकि, मैं एक प्रदर्शन समस्या की खोज की है: जब

SELECT *, (f_citizen_rec_modified(col1, col2)).* 
FROM v_citizenversions v 

चल f_citizen_rec_modified समारोह प्रत्येक स्तंभ यह रिटर्न (v_citizenversions में हर पंक्ति से गुणा) के लिए 1 बार भाग गया हो जाएगा । मुझे इस प्रभाव के लिए प्रलेखन नहीं मिला, लेकिन इसे डिबगिंग द्वारा इसे कम करने में सक्षम था। अब प्रश्न बन जाता है, इस प्रभाव को बिना किसी प्रभाव के रोबिंग के इस प्रभाव के बिना हम इस प्रभाव को कैसे प्राप्त कर सकते हैं (9.3 से पहले जहां पार्श्व जुड़ना उपलब्ध है)?

अद्यतन: मुझे एक उत्तर मिल गया है। क्वेरी पुनर्लेखन इस प्रकार है:

select x.col1, x.col2, x.col3, (x.func).* 
FROM (select SELECT v.col1, v.col2, v.col3, f_citizen_rec_modified(col1, col2) func 
FROM v_citizenversions v) x 

मुख्य अंतर पहले कच्चे समारोह परिणाम प्राप्त करने जा रहा है (भीतरी सबक्वेरी) तो लपेटकर कि किसी अन्य रूप में स्तंभों में चयन कि प्रतिमाएं उन परिणामों से बाहर। इस पीजी पर परीक्षण किया गया था 9.2

9

Necromancing: PostgreSQL 9.3 में
नई:

पार्श्व कीवर्ड

छोड़ दिया | सही | भीतरी शामिल हों पार्श्व

INNER JOIN LATERAL रूप CROSS APPLY
और LEFT JOIN LATERAL एक ही एक ही रूप में OUTER APPLY

उदाहरण उपयोग है:

SELECT * FROM T_Contacts 

--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1 
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989 


LEFT JOIN LATERAL 
(
    SELECT 
     --MAP_CTCOU_UID  
     MAP_CTCOU_CT_UID 
     ,MAP_CTCOU_COU_UID 
     ,MAP_CTCOU_DateFrom 
     ,MAP_CTCOU_DateTo 
    FROM T_MAP_Contacts_Ref_OrganisationalUnit 
    WHERE MAP_CTCOU_SoftDeleteStatus = 1 
    AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID 

    /* 
    AND 
    ( 
     (__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo) 
     AND 
     (__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom) 
    ) 
    */ 
    ORDER BY MAP_CTCOU_DateFrom 
    LIMIT 1 
) AS FirstOE 
संबंधित मुद्दे