आदेश द्वारा पत्र और संख्याओं के मिश्रित तार की तुलना


9

हमें उन मूल्यों पर कुछ रिपोर्टिंग करने की आवश्यकता है जो आमतौर पर संख्याओं और अक्षरों के मिश्रित तार होते हैं जिन्हें 'स्वाभाविक रूप से' सॉर्ट करने की आवश्यकता होती है। चीजें जैसे, "P7B18" या "P12B3"। @ तार ज्यादातर अक्षरों के क्रम होंगे, फिर बारी-बारी से संख्याएँ। हालांकि इन खंडों की संख्या और प्रत्येक की लंबाई अलग-अलग हो सकती है।

हम सांख्यिक क्रम में क्रमबद्ध किए जाने के लिए इनमें से संख्यात्मक भागों को पसंद करेंगे। जाहिर है, अगर मैं सीधे उन स्ट्रिंग मानों को ORDER BYसंभालता हूं, तो "P12B3" "P7B18" से पहले आने वाला है, क्योंकि "P1" "P7" से पहले का है, लेकिन मैं "P7" को स्वाभाविक रूप से पूर्ववर्ती कहूंगा; "P12"।

मैं भी तुलना करने में सक्षम होना चाहते हैं, जैसे @bin < 'P13S6'या कुछ ऐसे। मुझे फ्लोटिंग पॉइंट या नेगेटिव नंबरों को हैंडल करने की ज़रूरत नहीं है; ये कड़ाई से गैर-नकारात्मक पूर्णांक होंगे जो हम काम कर रहे हैं। स्ट्रिंग की लंबाई और सेगमेंट की संख्या संभावित रूप से मनमानी हो सकती है, जिसमें कोई निश्चित ऊपरी सीमा नहीं है।

हमारे मामले में, स्ट्रिंग केसिंग महत्वपूर्ण नहीं है, हालांकि अगर एक टक्कर-जागरूक फैशन में ऐसा करने का एक तरीका है, तो अन्य को यह उपयोगी लग सकता है। इस सब का सबसे बदसूरत हिस्सा है कि मैं दोनों ऑर्डर करने में सक्षम होना चाहूंगा, और WHEREक्लॉज में रेंज फ़िल्टरिंग कर सकता हूं ।

अगर मैं C # में ऐसा कर रहा था, तो यह बहुत आसान काम होगा: अल्फा को संख्यात्मक से अलग करने के लिए कुछ पार्सिंग करें, IComparable को लागू करें, और आप मूल रूप से कर रहे हैं। SQL सर्वर, निश्चित रूप से किसी भी समान कार्यक्षमता की पेशकश करने के लिए प्रकट नहीं होता है, कम से कम जहां तक ​​मैं जानता हूं।

किसी को भी यह काम करने के लिए कोई अच्छी चाल पता है? क्या कस्टम CLR प्रकार बनाने के लिए कुछ कम प्रचारित क्षमता है जो IComparable को लागू करती है और क्या यह अपेक्षा के अनुरूप व्यवहार करती है? मैं स्टूपिड एक्सएमएल ट्रिक्स (यह भी देखें: सूची मिलान) का विरोध नहीं कर रहा हूं, और मुझे सर्वर पर उपलब्ध सीएलआर रेगेक्स मिलान / एक्सट्रैक्टिंग / रिप्लेसमेंट रैपर फ़ंक्शन भी मिल गए हैं।

संपादित करें: थोड़ा अधिक विस्तृत उदाहरण के रूप में, मैं चाहता हूं कि डेटा कुछ इस तरह का व्यवहार करे।

SELECT bin FROM bins ORDER BY bin

bin
--------------------
M7R16L
P8RF6JJ
P16B5
PR7S19
PR7S19L
S2F3
S12F0

यानी सभी अक्षरों या सभी नंबरों के टोकन में स्ट्रिंग्स को तोड़ें, और उन्हें क्रमशः वर्णक्रमानुसार या संख्यात्मक रूप से क्रमबद्ध करें, जिसमें सबसे बाएं टोकन सबसे महत्वपूर्ण छँटाई शब्द है। जैसे मैंने उल्लेख किया है। यदि आप IComparable को लागू करते हैं, तो .NET में केक का टुकड़ा है, लेकिन मुझे नहीं पता कि कैसे (या यदि) आप SQL सर्वर में उस तरह का काम कर सकते हैं। यह निश्चित रूप से ऐसा कुछ नहीं है जो मैं कभी भी 10 या इसके साथ काम करने के वर्षों में आया हूं।


आप इसे किसी प्रकार के अनुक्रमित कम्प्यूटेड कॉलम के साथ कर सकते हैं, स्ट्रिंग को पूर्णांक में बदल सकते हैं। तो P7B12बन सकता है P 07 B 12, तो (ASCII के माध्यम से) 80 07 65 12, इसलिए80076512
Phil

मेरा सुझाव है कि आप एक परिकलित स्तंभ बनाएँ, जो प्रत्येक सांख्यिक घटक को एक बड़ी लंबाई (यानी 10 शून्य) में रखता है। चूंकि प्रारूप बहुत मनमाना है, आपको एक बहुत बड़ी इनलाइन अभिव्यक्ति की आवश्यकता होगी, लेकिन यह उल्लेखनीय है। जब आप अपनी पसंद के अनुसार उस स्तंभ पर / जहां / जहां तक ​​अनुक्रमित / आदेश कर सकते हैं।
Nick.McD मत्स्यांगना

कृपया वह लिंक देखें जिसे मैंने अपने उत्तर के शीर्ष पर जोड़ा है :)
सोलोमन रटज़की

1
@srutzky नाइस, मैंने इसके लिए मतदान किया।
db2

हे db2: Microsoft कनेक्ट ओवर से उपयोगकर्तावॉइस पर जाने के कारण और वोट की गिनती को ठीक से नहीं रखने के कारण (उन्होंने इसे एक टिप्पणी में डाल दिया, लेकिन निश्चित रूप से वे इसे नहीं देखते हैं), आपको इसके लिए फिर से वोट करने की आवश्यकता हो सकती है: समर्थन "प्राकृतिक छँटाई" / DIGITSASNUMBERS एक Collation विकल्प के रूप में । धन्यवाद!
सोलोमन रटज़की

जवाबों:


8

वास्तविक संख्या के रूप में तार में संख्याओं को छांटने का एक समझदार, कुशल साधन चाहते हैं? मेरे Microsoft कनेक्ट सुझाव के लिए मतदान करने पर विचार करें: "प्राकृतिक सॉर्टिंग" / DIGITSASNUMBERS को एक Collation विकल्प के रूप में समर्थन करें


ऐसा करने का कोई आसान, अंतर्निहित साधन नहीं है, लेकिन यहां एक संभावना है:

फिक्स्ड-लेंथ सेगमेंट में सुधार करके स्ट्रिंग्स को सामान्य करें:

  • एक प्रकार का स्तंभ बनाएं VARCHAR(50) COLLATE Latin1_General_100_BIN2। 50 की अधिकतम लंबाई को सेगमेंट की अधिकतम संख्या और उनकी संभावित अधिकतम लंबाई के आधार पर समायोजित करने की आवश्यकता हो सकती है।
  • जबकि सामान्यीकरण ऐप परत में अधिक कुशलता से किया जा सकता है, टी-एसक्यूएल यूडीएफ का उपयोग करके डेटाबेस में इसे संभालना स्केलर यूडीएफ को AFTER [or FOR] INSERT, UPDATEट्रिगर में रखने की अनुमति देगा, जैसे कि आप सभी रिकॉर्डों के लिए उचित मूल्य निर्धारित करने की गारंटी देते हैं, यहां तक ​​कि तदर्थ प्रश्नों, आदि के माध्यम से आ रहा है, निश्चित रूप से, कि स्केलर UDF को SQLCLR के माध्यम से भी नियंत्रित किया जा सकता है, लेकिन यह निर्धारित करने के लिए परीक्षण किया जाना चाहिए कि वास्तव में कौन अधिक कुशल था। **
  • UDF (T-SQL या SQLCLR में होने की परवाह किए बिना) होना चाहिए:
    • प्रत्येक वर्ण को पढ़कर और प्रकार को अल्फा से संख्यात्मक या संख्यात्मक से अल्फा पर स्विच करने पर अज्ञात सेगमेंट की प्रक्रिया करें।
    • प्रत्येक सेगमेंट के अनुसार इसे किसी भी सेगमेंट के अधिकतम संभव अक्षर / अंकों (या भविष्य में विकास के लिए अधिकतम + 1 या 2) के लिए एक निश्चित लंबाई का स्ट्रिंग सेट करना चाहिए।
    • अल्फा सेगमेंट को बाएं-जस्टिफ़ाइड और राइट-पैडेड स्पेस के साथ होना चाहिए।
    • शून्य सेगमेंट के साथ न्यूमेरिक सेगमेंट को सही-सही और बाएं-पैडेड होना चाहिए।
    • यदि अल्फा वर्ण मिश्रित-केस के रूप में आ सकते हैं, लेकिन ऑर्डर को केस-असंवेदनशील होने की आवश्यकता है, तो UPPER()फ़ंक्शन को सभी सेगमेंट के अंतिम परिणाम पर लागू करें (ताकि इसे केवल एक बार करने की आवश्यकता हो और प्रति सेगमेंट नहीं)। यह सॉर्ट कॉलम के बाइनरी कोलेशन को देखते हुए उचित छँटाई के लिए अनुमति देगा।
  • AFTER INSERT, UPDATEतालिका पर एक ट्रिगर बनाएं जो सॉर्ट कॉलम सेट करने के लिए यूडीएफ को बुलाता है। प्रदर्शन में सुधार करने के लिए, UPDATE()यह निर्धारित करने के लिए फ़ंक्शन का उपयोग करें कि क्या यह कोड कॉलम स्टेटमेंट के SETक्लॉज में है UPDATE(बस RETURNयदि गलत है), और फिर कोड कॉलम में केवल प्रक्रिया पंक्तियों में बदलाव करने वाली पंक्तियों के लिए कोड स्तंभ पर INSERTEDऔर DELETEDछद्म तालिकाओं को मिलाएं। । COLLATE Latin1_General_100_BIN2यदि कोई परिवर्तन है तो निर्धारित करने में सटीकता सुनिश्चित करने के लिए उस JOIN स्थिति पर निर्दिष्ट करना सुनिश्चित करें।
  • नए सॉर्ट कॉलम पर एक इंडेक्स बनाएं।

उदाहरण:

P7B18   -> "P     000007B     000018"
P12B3   -> "P     000012B     000003"
P12B3C8 -> "P     000012B     000003C     000008"

इस दृष्टिकोण में, आप इसके माध्यम से सॉर्ट कर सकते हैं:

ORDER BY tbl.SortColumn

और आप के माध्यम से रेंज फ़िल्टरिंग कर सकते हैं:

WHERE tbl.SortColumn BETWEEN dbo.MyUDF('P7B18') AND dbo.MyUDF('P12B3')

या:

DECLARE @RangeStart VARCHAR(50),
        @RangeEnd VARCHAR(50);
SELECT @RangeStart = dbo.MyUDF('P7B18'),
       @RangeEnd = dbo.MyUDF('P12B3');

WHERE tbl.SortColumn BETWEEN @RangeStart AND @RangeEnd

दोनों ORDER BYऔर WHEREफिल्टर SortColumnको Collation Precedence के कारण परिभाषित बाइनरी कोलेशन का उपयोग करना चाहिए ।

समानता मूल्य अभी भी मूल मूल्य स्तंभ पर किया जाएगा।


अन्य विचार:

  • SQLCLR UDT का उपयोग करें। यह काम कर सकता है, हालांकि यह स्पष्ट नहीं है कि यह ऊपर वर्णित दृष्टिकोण की तुलना में शुद्ध लाभ प्राप्त करता है।

    हाँ, SQLCLR UDT के कस्टम एल्गोरिदम के साथ इसके तुलनात्मक ऑपरेटर ओवरराइड हो सकते हैं। यह उन स्थितियों को संभालता है, जहां मूल्य की तुलना किसी अन्य मूल्य से की जा रही है, जो पहले से ही एक ही कस्टम प्रकार है, या एक जिसे परिवर्तित करने की आवश्यकता है। यह एक हालत में रेंज फिल्टर को संभालना चाहिएWHERE

    UDT को एक नियमित कॉलम प्रकार (एक संगणित कॉलम नहीं) के रूप में क्रमबद्ध करने के संबंध में, यह केवल तभी संभव है जब UDT "बाइट ऑर्डर किया गया" हो। "बाइट ऑर्डर" होने का मतलब है कि यूडीटी का द्विआधारी प्रतिनिधित्व (जिसे यूडीटी में परिभाषित किया जा सकता है) स्वाभाविक रूप से उचित क्रम में सॉर्ट करता है। यह मानते हुए कि द्विआधारी प्रतिनिधित्व को VARCHAR (50) स्तंभ के लिए ऊपर वर्णित दृष्टिकोण के समान संभाला जाता है, जिसमें निश्चित लंबाई वाले खंड होते हैं जो कि गद्देदार होते हैं, जो अर्हता प्राप्त करेंगे। या, यदि यह सुनिश्चित करना आसान नहीं था कि द्विआधारी प्रतिनिधित्व स्वाभाविक रूप से उचित तरीके से आदेश दिया जाएगा, तो आप यूडीटी की एक विधि या संपत्ति को उजागर कर सकते हैं जो एक मूल्य का उत्पादन करता है जो ठीक से आदेश दिया जाएगा, और फिर PERSISTEDउस पर एक गणना कॉलम बना सकते हैं विधि या संपत्ति। विधि को नियतात्मक और के रूप में चिह्नित करने की आवश्यकता है IsDeterministic = true

    इस दृष्टिकोण के लाभ हैं:

    • "मूल मान" फ़ील्ड की आवश्यकता नहीं है।
    • डेटा डालने या मूल्यों की तुलना करने के लिए UDF को कॉल करने की आवश्यकता नहीं है। यह मानते हुए कि Parseयूडीटी की विधि P7B18मूल्य में ले जाती है और इसे रूपांतरित करती है, तो आपको बस स्वाभाविक रूप से मानों को सम्मिलित करने में सक्षम होना चाहिए P7B18। और यूडीटी में निहित निहित रूपान्तरण विधि के साथ, WHERE की स्थिति भी बस P7B18` का उपयोग करने की अनुमति देगी।

    इस दृष्टिकोण के परिणाम हैं:

    • यदि बाइट का उपयोग करके UDT को स्तंभ डेटाटाइप के रूप में उपयोग किया जाता है, तो बस फ़ील्ड का चयन करना बाइनरी प्रतिनिधित्व को वापस कर देगा। या PERSISTEDयूडीटी की संपत्ति या विधि पर एक गणना किए गए कॉलम का उपयोग करते हैं, तो आपको संपत्ति या विधि द्वारा वापस लौटाया गया प्रतिनिधित्व मिलेगा। यदि आप मूल P7B18मूल्य चाहते हैं , तो आपको यूडीटी की एक विधि या संपत्ति को कॉल करने की आवश्यकता है जो उस प्रतिनिधित्व को वापस करने के लिए कोडित है। चूँकि आपको ToStringविधि को वैसे भी ओवरराइड करना होगा , इसलिए यह प्रदान करने के लिए एक अच्छा उम्मीदवार है।
    • यह स्पष्ट नहीं है (कम से कम मेरे लिए अभी से जब से मैंने इस भाग का परीक्षण नहीं किया है) बाइनरी प्रतिनिधित्व में कोई भी बदलाव करना कितना आसान / कठिन होगा। संग्रहीत को बदलना, सॉर्ट करने योग्य प्रतिनिधित्व को छोड़ने और क्षेत्र को फिर से जोड़ने की आवश्यकता हो सकती है। इसके अलावा, यूडीटी युक्त असेंबली को गिराना यदि किसी भी तरीके से उपयोग किया जाता है, तो यह विफल हो जाएगा, इसलिए आप यह सुनिश्चित करना चाहेंगे कि इस यूडीटी के अलावा विधानसभा में और कुछ नहीं था। आप ALTER ASSEMBLYपरिभाषा को बदल सकते हैं , लेकिन उस पर कुछ प्रतिबंध हैं।

      दूसरी ओर, VARCHAR()फ़ील्ड डेटा है जिसे एल्गोरिथ्म से डिस्कनेक्ट किया गया है, इसलिए इसे केवल कॉलम को अपडेट करने की आवश्यकता होगी। और अगर लाखों पंक्तियाँ (या अधिक) हैं तो वह एक बैचबद्ध दृष्टिकोण में किया जा सकता है।

  • आईसीयू पुस्तकालय को लागू करें जो वास्तव में इस अल्फ़ान्यूमेरिक सॉर्टिंग को करने की अनुमति देता है। अत्यधिक कार्यात्मक होते हुए, पुस्तकालय केवल दो भाषाओं में आता है: C / C ++ और Java। इसका मतलब है कि आपको विजुअल C ++ में काम करने के लिए या तो कुछ ट्वीक्स करने की आवश्यकता हो सकती है, या इस बात की संभावना है कि IKVM का उपयोग करके जावा कोड को MSIL में परिवर्तित किया जा सकता है । उस साइट पर एक या दो .NET साइड प्रोजेक्ट जुड़े हुए हैं जो एक COM इंटरफ़ेस प्रदान करते हैं जिसे प्रबंधित कोड में एक्सेस किया जा सकता है, लेकिन मेरा मानना ​​है कि उन्हें थोड़ी देर में अपडेट नहीं किया गया है और मैंने उन्हें आज़माया नहीं है। यहाँ सबसे अच्छी शर्त यह होगी कि इसे एप्लिकेशन लेयर में सॉर्ट कीज़ बनाने के लक्ष्य के साथ हैंडल किया जाए। फिर सॉर्ट कीज़ को एक नए सॉर्ट कॉलम में सहेजा जाएगा।

    यह सबसे व्यावहारिक दृष्टिकोण नहीं हो सकता है। हालांकि, यह अभी भी बहुत अच्छा है कि ऐसी क्षमता मौजूद है। मैंने निम्नलिखित उत्तर में इसका एक और अधिक विस्तृत वॉक-थ्रू प्रदान किया:

    क्या निम्नलिखित क्रम 1,2,3,6,10,10A, 10B, 11 में निम्नलिखित तारों को क्रमबद्ध करने के लिए कोई टकराव है?

    लेकिन उस प्रश्न से निपटा जा रहा पैटर्न थोड़ा सरल है। एक उदाहरण के लिए, जिसमें दिखाया गया है कि इस प्रश्न में किस प्रकार का पैटर्न है, यह भी काम करता है, कृपया निम्न पृष्ठ पर जाएं:

    ICU Collation Demo

    "सेटिंग" के तहत, "संख्यात्मक" विकल्प को "चालू" पर सेट करें और अन्य सभी को "डिफ़ॉल्ट" पर सेट किया जाना चाहिए। अगला, "सॉर्ट" बटन के दाईं ओर, "अलग-अलग ताकत" के लिए विकल्प को अनचेक करें और "सॉर्ट कुंजी" के लिए विकल्प की जांच करें। फिर निम्नलिखित सूची के साथ "इनपुट" टेक्स्ट क्षेत्र में आइटम की सूची को बदलें:

    P12B22
    P7B18
    P12B3
    as456456hgjg6786867
    P7Bb19
    P7BA19
    P7BB19
    P007B18
    P7Bb20
    P7Bb19z23

    "सॉर्ट" बटन पर क्लिक करें। "आउटपुट" पाठ क्षेत्र को निम्नलिखित प्रदर्शित करना चाहिए:

    as456456hgjg6786867
        29 4D 0F 7A EA C8 37 35 3B 35 0F 84 17 A7 0F 93 90 , 0D , , 0D .
    P7B18
        47 0F 09 2B 0F 14 , 08 , FD F1 , DC C5 DC 05 .
    P007B18
        47 0F 09 2B 0F 14 , 08 , FD F1 , DC C5 DC 05 .
    P7BA19
        47 0F 09 2B 29 0F 15 , 09 , FD FF 10 , DC C5 DC DC 05 .
    P7Bb19
        47 0F 09 2B 2B 0F 15 , 09 , FD F2 , DC C5 DC 06 .
    P7BB19
        47 0F 09 2B 2B 0F 15 , 09 , FD FF 10 , DC C5 DC DC 05 .
    P7Bb19z23
        47 0F 09 2B 2B 0F 15 5B 0F 19 , 0B , FD F4 , DC C5 DC 08 .
    P7Bb20
        47 0F 09 2B 2B 0F 16 , 09 , FD F2 , DC C5 DC 06 .
    P12B3
        47 0F 0E 2B 0F 05 , 08 , FD F1 , DC C5 DC 05 .
    P12B22
        47 0F 0E 2B 0F 18 , 08 , FD F1 , DC C5 DC 05 .

    कृपया ध्यान दें कि विभिन्न कुंजियों में क्रमबद्ध कुंजियाँ कॉमा द्वारा अलग की गई हैं। प्रत्येक फ़ील्ड को स्वतंत्र रूप से सॉर्ट करने की आवश्यकता होती है, ताकि SQL सर्वर में इसे लागू करने की आवश्यकता होने पर हल करने के लिए एक और छोटी समस्या प्रस्तुत हो।


** यदि उपयोगकर्ता-परिभाषित कार्यों के उपयोग के बारे में प्रदर्शन के बारे में कोई चिंता है, तो कृपया ध्यान दें कि प्रस्तावित दृष्टिकोण उनमें से न्यूनतम उपयोग करते हैं। वास्तव में, सामान्यीकृत मूल्य को संग्रहीत करने का मुख्य कारण प्रत्येक क्वेरी की प्रत्येक पंक्ति में एक यूडीएफ को कॉल करने से बचना था। प्राथमिक दृष्टिकोण में, यूडीएफ का उपयोग मूल्य निर्धारित करने के लिए किया जाता है SortColumn, और यह केवल ट्रिगर पर INSERTऔर उसके UPDATEमाध्यम से किया जाता है । मानों का चयन करना डालने और अद्यतन करने की तुलना में बहुत अधिक सामान्य है, और कुछ मूल्य कभी भी अपडेट नहीं किए जाते हैं। प्रत्येक SELECTक्वेरी के अनुसार SortColumnजो WHEREक्लॉज में एक रेंज फिल्टर के लिए उपयोग करता है , यूडीएफ को सामान्यीकृत मान प्राप्त करने के लिए प्रत्येक रेंज_स्टार्ट और रेंज_एंड मानों में से प्रत्येक में एक समय की आवश्यकता होती है; यूडीएफ को प्रति पंक्ति नहीं कहा जाता है।

यूडीटी के संबंध में, उपयोग वास्तव में स्केलर यूडीएफ के साथ ही है। मतलब, डालने और अद्यतन करने के लिए मूल्य निर्धारित करने के लिए प्रत्येक पंक्ति में एक बार सामान्यीकरण विधि को कॉल करना होगा। फिर, एक रेंज फिल्टर में प्रत्येक रेंज_स्टार्ट और रेंज_वल्यू के अनुसार प्रति बार एक बार सामान्यीकरण विधि को बुलाया जाएगा, लेकिन प्रति पंक्ति नहीं।

SQLCLR UDF में पूरी तरह से सामान्यीकरण को संभालने के पक्ष में एक बिंदु यह है कि यह किसी भी डेटा का उपयोग नहीं कर रहा है और नियतात्मक है, यदि इसे चिह्नित किया गया है IsDeterministic = true, तो यह समानांतर योजनाओं (जो संचालन INSERTऔर UPDATEसंचालन में मदद कर सकता है ) में भाग ले सकता है जबकि T-SQL UDF एक समानांतर योजना को इस्तेमाल होने से रोकेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.