एक बहुत ही सरल उदाहरण होगा:
> SELECT * FROM tab ORDER BY col USING <
लेकिन यह उबाऊ है, क्योंकि यह कुछ भी नहीं है जो आपको पारंपरिक ORDER BY col ASC
के साथ नहीं मिल सकता है .
इसके अलावा मानक कैटलॉग अजीब तुलना कार्यों/ऑपरेटरों के बारे में रोमांचक कुछ भी उल्लेख नहीं करता है। आप उनकी सूची प्राप्त कर सकते हैं:
> SELECT amoplefttype::regtype, amoprighttype::regtype, amopopr::regoper
FROM pg_am JOIN pg_amop ON pg_am.oid = pg_amop.amopmethod
WHERE amname = 'btree' AND amopstrategy IN (1,5);
आप देखेंगे, कि अधिकतर <
. हैं और >
integer
. जैसे आदिम प्रकारों के लिए कार्य , date
आदि और कुछ और सरणियों और वैक्टर के लिए और इसी तरह। इनमें से कोई भी ऑपरेटर आपको कस्टम ऑर्डरिंग प्राप्त करने में मदद नहीं करेगा।
अधिकांश . में ऐसे मामले जहां कस्टम ऑर्डरिंग की आवश्यकता होती है, आप ... ORDER BY somefunc(tablecolumn) ...
जैसी किसी चीज़ का उपयोग करके दूर हो सकते हैं जहां somefunc
मूल्यों को उचित रूप से मानचित्रित करता है। क्योंकि यह हर डेटाबेस के साथ काम करता है, यह भी सबसे आम तरीका है। साधारण चीज़ों के लिए आप कस्टम फ़ंक्शन के बजाय एक एक्सप्रेशन भी लिख सकते हैं।
गियर ऊपर स्विच करना
ORDER BY ... USING
कई मामलों में समझ में आता है:
- आदेश इतना असामान्य है कि
somefunc
चाल काम नहीं करती। - आप गैर-आदिम प्रकार के साथ काम करते हैं (जैसे
point
,circle
या काल्पनिक संख्याएं) और आप अजीब गणनाओं के साथ अपने प्रश्नों में खुद को दोहराना नहीं चाहते हैं। - जिस डेटासेट को आप सॉर्ट करना चाहते हैं वह इतना बड़ा है कि इंडेक्स द्वारा समर्थन वांछित या आवश्यक भी है।
मैं जटिल डेटाटाइप पर ध्यान केंद्रित करूंगा:अक्सर उन्हें उचित तरीके से क्रमबद्ध करने के एक से अधिक तरीके होते हैं। एक अच्छा उदाहरण है point
:आप उन्हें (0,0) की दूरी या x . द्वारा "आदेश" दे सकते हैं पहले, फिर y . द्वारा या केवल y . द्वारा या कुछ और जो आप चाहते हैं।
बेशक, PostgreSQL है point
. के लिए पूर्वनिर्धारित ऑपरेटर :
> CREATE TABLE p ( p point );
> SELECT p <-> point(0,0) FROM p;
लेकिन कोई नहीं उनमें से ORDER BY
. के लिए प्रयोग करने योग्य घोषित किया गया है डिफ़ॉल्ट रूप से (ऊपर देखें):
> SELECT * FROM p ORDER BY p;
ERROR: could not identify an ordering operator for type point
TIP: Use an explicit ordering operator or modify the query.
point
. के लिए सरल ऑपरेटर "नीचे" और "ऊपर" ऑपरेटर हैं <^
और >^
. वे बस y
. की तुलना करते हैं बिंदु का हिस्सा। लेकिन:
> SELECT * FROM p ORDER BY p USING >^;
ERROR: operator > is not a valid ordering operator
TIP: Ordering operators must be "<" or ">" members of __btree__ operator families.
ORDER BY USING
परिभाषित शब्दार्थ के साथ एक ऑपरेटर की आवश्यकता है:जाहिर है कि यह एक बाइनरी ऑपरेटर होना चाहिए, इसे उसी प्रकार के तर्कों को स्वीकार करना चाहिए और इसे बूलियन वापस करना होगा। मुझे लगता है कि यह भी संक्रमणीय होना चाहिए (यदि ए <बी और बी <सी तो ए <सी)। अधिक आवश्यकताएं हो सकती हैं। लेकिन ये सभी आवश्यकताएं उचित btree . के लिए भी आवश्यक हैं -इंडेक्स ऑर्डरिंग। यह btree . के संदर्भ वाले अजीब त्रुटि संदेशों की व्याख्या करता है .
ORDER BY USING
केवल एक ऑपरेटर . की भी आवश्यकता नहीं है परिभाषित किया जाना है लेकिन एक ऑपरेटर वर्ग और एक संचालक परिवार . जबकि एक कर सकता था केवल एक ऑपरेटर के साथ छँटाई लागू करें, PostgreSQL कुशलतापूर्वक सॉर्ट करने और तुलनाओं को कम करने का प्रयास करता है। इसलिए, जब आप केवल एक निर्दिष्ट करते हैं तब भी कई ऑपरेटरों का उपयोग किया जाता है - अन्य को कुछ गणितीय बाधाओं का पालन करना चाहिए - मैंने पहले ही ट्रांज़िटिविटी का उल्लेख किया है, लेकिन और भी हैं।
गियर ऊपर स्विच करना
आइए कुछ उपयुक्त परिभाषित करें:बिंदुओं के लिए एक ऑपरेटर जो केवल y
. की तुलना करता है भाग।
पहला कदम एक कस्टम ऑपरेटर परिवार बनाना है जिसका उपयोग btree . द्वारा किया जा सकता है इंडेक्स एक्सेस विधि। देखें
> CREATE OPERATOR FAMILY xyzfam USING btree; -- superuser access required!
CREATE OPERATOR FAMILY
आगे हमें एक तुलनित्र फ़ंक्शन प्रदान करना चाहिए जो दो बिंदुओं की तुलना करते समय -1, 0, +1 देता है। यह कार्य होगा आंतरिक रूप से बुलाया जाए!
> CREATE FUNCTION xyz_v_cmp(p1 point, p2 point) RETURNS int
AS $$BEGIN RETURN btfloat8cmp(p1[1],p2[1]); END $$ LANGUAGE plpgsql;
CREATE FUNCTION
आगे हम परिवार के लिए ऑपरेटर वर्ग को परिभाषित करते हैं। संख्याओं की व्याख्या के लिए मैनुअल देखें।
> CREATE OPERATOR CLASS xyz_ops FOR TYPE point USING btree FAMILY xyzfam AS
OPERATOR 1 <^ ,
OPERATOR 3 ?- ,
OPERATOR 5 >^ ,
FUNCTION 1 xyz_v_cmp(point, point) ;
CREATE OPERATOR CLASS
यह कदम कई ऑपरेटरों और कार्यों को जोड़ता है और उनके संबंध और अर्थ को भी परिभाषित करता है। उदाहरण के लिए OPERATOR 1
इसका अर्थ है:यह less-than
के लिए ऑपरेटर है परीक्षण।
अब ऑपरेटर्स <^
और >^
ORDER BY USING
. में इस्तेमाल किया जा सकता है :
> INSERT INTO p SELECT point(floor(random()*100), floor(random()*100)) FROM generate_series(1, 5);
INSERT 0 5
> SELECT * FROM p ORDER BY p USING >^;
p
---------
(17,8)
(74,57)
(59,65)
(0,87)
(58,91)
वोइला - y . द्वारा क्रमबद्ध ।
समाप्ति के लिए: ORDER BY ... USING
PostgreSQL के हुड के नीचे एक दिलचस्प नज़र है। लेकिन जब तक आप बहुत . में काम नहीं करते हैं, तब तक आपको किसी भी समय किसी भी चीज़ की आवश्यकता नहीं होगी डेटाबेस प्रौद्योगिकी के विशिष्ट क्षेत्र।
एक और उदाहरण पोस्टग्रेज डॉक्स में पाया जा सकता है। उदाहरण के लिए स्रोत कोड के साथ यहां और यहां । यह उदाहरण यह भी दिखाता है कि ऑपरेटरों को कैसे बनाया जाता है।