तो यहाँ मेरा परिदृश्य है:
मैं अपनी एक परियोजना के लिए स्थानीयकरण पर काम कर रहा हूं, और आमतौर पर मैं इसे C # कोड में करने के बारे में बताता हूं, हालांकि मैं इसे SQL में थोड़ा और अधिक करना चाहता हूं क्योंकि मैं अपने SQL को थोड़ा ऊपर करने की कोशिश कर रहा हूं।
पर्यावरण: SQL सर्वर 2014 मानक, C # (.NET 4.5.1)
नोट: प्रोग्रामिंग भाषा स्वयं अप्रासंगिक होनी चाहिए, मैं केवल इसे पूर्णता के लिए शामिल कर रहा हूं।
इसलिए मैंने जो चाहा, उसे पूरा किया, लेकिन उस हद तक नहीं जितना मैं चाहता था। जब से मैंने कोई एसक्यूएल JOIN
एस किया है, तब तक यह थोड़ी देर (कम से कम एक वर्ष) की है, लेकिन यह काफी जटिल है JOIN
।
यहां डेटाबेस के संबंधित तालिकाओं का एक आरेख है। (बहुत अधिक हैं, लेकिन इस हिस्से के लिए आवश्यक नहीं हैं।)
छवि में वर्णित सभी रिश्ते डेटाबेस में पूर्ण हैं - PK
और FK
बाधाएं सभी सेटअप और ऑपरेटिंग हैं। वर्णित कोई भी स्तंभ null
सक्षम नहीं हैं। सभी तालिकाओं में स्कीमा है dbo
।
अब, मेरे पास एक क्वेरी है जो लगभग वही करता है जो मैं चाहता हूं: अर्थात, किसी भी प्रकार की कोई आईडी SupportCategories
और कोई भी आईडी दी जाती है Languages
, यह या तो वापस आ जाएगी:
अगर वहाँ है कि स्ट्रिंग के लिए उस भाषा (IE के लिए एक सही उचित अनुवाद है StringKeyId
-> StringKeys.Id
मौजूद है, और में LanguageStringTranslations
StringKeyId
, LanguageId
है, और StringTranslationId
संयोजन मौजूद है, तो यह भार StringTranslations.Text
है कि के लिए StringTranslationId
।
तो LanguageStringTranslations
StringKeyId
, LanguageId
है, और StringTranslationId
संयोजन किया नहीं मौजूद है, तो यह लोड करता है StringKeys.Name
मूल्य। Languages.Id
एक दिया जाता है integer
।
मेरी क्वेरी, यह एक गड़बड़ है, इस प्रकार है:
SELECT CASE WHEN T.x IS NOT NULL THEN T.x ELSE (SELECT
CASE WHEN dbo.StringTranslations.Text IS NULL THEN dbo.StringKeys.Name ELSE dbo.StringTranslations.Text END AS Result
FROM dbo.SupportCategories
INNER JOIN dbo.StringKeys
ON dbo.SupportCategories.StringKeyId = dbo.StringKeys.Id
INNER JOIN dbo.LanguageStringTranslations
ON dbo.StringKeys.Id = dbo.LanguageStringTranslations.StringKeyId
INNER JOIN dbo.StringTranslations
ON dbo.StringTranslations.Id = dbo.LanguageStringTranslations.StringTranslationId
WHERE dbo.LanguageStringTranslations.LanguageId = 38 AND dbo.SupportCategories.Id = 0) END AS Result FROM (SELECT (SELECT
CASE WHEN dbo.StringTranslations.Text IS NULL THEN dbo.StringKeys.Name ELSE dbo.StringTranslations.Text END AS Result
FROM dbo.SupportCategories
INNER JOIN dbo.StringKeys
ON dbo.SupportCategories.StringKeyId = dbo.StringKeys.Id
INNER JOIN dbo.LanguageStringTranslations
ON dbo.StringKeys.Id = dbo.LanguageStringTranslations.StringKeyId
INNER JOIN dbo.StringTranslations
ON dbo.StringTranslations.Id = dbo.LanguageStringTranslations.StringTranslationId
WHERE dbo.LanguageStringTranslations.LanguageId = 5 AND dbo.SupportCategories.Id = 0) AS x) AS T
समस्या यह है कि यह मुझे प्रदान करने में सक्षम नहीं है सभी की SupportCategories
है और उनके संबंधित StringTranslations.Text
यदि वह मौजूद है, या उनके StringKeys.Name
अगर यह मौजूद नहीं था। यह उनमें से किसी एक को प्रदान करने में एकदम सही है, लेकिन बिल्कुल भी नहीं। असल में, यह लागू करना है कि यदि किसी भाषा में किसी विशिष्ट कुंजी के लिए अनुवाद नहीं है, तो डिफ़ॉल्ट का उपयोग करना है StringKeys.Name
जो StringKeys.DefaultLanguageId
अनुवाद का है। (आदर्श रूप से, यह भी ऐसा नहीं करेगा, बल्कि इसके लिए अनुवाद को लोड करता है StringKeys.DefaultLanguageId
, जिसे मैं स्वयं कर सकता हूं यदि बाकी क्वेरी के लिए सही दिशा में बताया गया है।)
मैंने इस पर बहुत समय बिताया है, और मुझे पता है कि अगर मैं इसे सी # में लिखता (जैसे मैं आमतौर पर करता हूं) तो यह अब तक हो जाएगा। मैं एसक्यूएल में ऐसा करना चाहता हूं, और मुझे अपनी पसंद का आउटपुट प्राप्त करने में परेशानी हो रही है।
एकमात्र चेतावनी, क्या मैं लागू वास्तविक प्रश्नों की संख्या को सीमित करना चाहता हूं। सभी कॉलम अनुक्रमित हैं और जैसे कि मैं उन्हें अभी के लिए पसंद करता हूं, और वास्तविक तनाव-परीक्षण के बिना मैं उन्हें और अनुक्रमित नहीं कर सकता।
संपादित करें: एक और ध्यान दें, मैं डेटाबेस को यथासंभव सामान्य रखने की कोशिश कर रहा हूं, इसलिए मैं चीजों को डुप्लिकेट नहीं करना चाहता अगर मैं इससे बच सकता हूं।
उदाहरण डेटा
स्रोत
dbo.SupportCategories (संपूर्ण):
Id StringKeyId
0 0
1 1
2 2
dbo.Languages (185 रिकॉर्ड, उदाहरण के लिए केवल दो दिखा रहा है):
Id Abbreviation Family Name Native
38 en Indo-European English English
48 fr Indo-European French français, langue française
dbo.LanguagesStringTranslations (संपूर्ण):
StringKeyId LanguageId StringTranslationId
0 38 0
1 38 1
2 38 2
3 38 3
4 38 4
5 38 5
6 38 6
7 38 7
1 48 8 -- added as example
dbo.StringKeys (संपूर्ण):
Id Name DefaultLanguageId
0 Billing 38
1 API 38
2 Sales 38
3 Open 38
4 Waiting for Customer 38
5 Waiting for Support 38
6 Work in Progress 38
7 Completed 38
dbo.StringTranslations (संपूर्ण):
Id Text
0 Billing
1 API
2 Sales
3 Open
4 Waiting for Customer
5 Waiting for Support
6 Work in Progress
7 Completed
8 Les APIs -- added as example
मौजूदा उत्पादन
नीचे सटीक क्वेरी को देखते हुए, यह आउटपुट करता है:
Result
Billing
वांछित उत्पादन
आदर्श रूप से, मैं विशिष्ट को छोड़ना चाहता हूं SupportCategories.Id
, और उन सभी को प्राप्त करना चाहता हूं, जैसे कि (भले ही भाषा 38 English
का उपयोग किया गया हो, या 48 French
, या किसी भी अन्य भाषा इस समय):
Id Result
0 Billing
1 API
2 Sales
अतिरिक्त उदाहरण
यह देखते हुए कि मुझे French
(Ie ऐड ) के लिए एक स्थानीयकरण जोड़ना 1 48 8
था LanguageStringTranslations
, आउटपुट बदल जाएगा (नोट: यह केवल उदाहरण के लिए है, जाहिर है मैं एक स्थानीय स्ट्रिंग जोड़ूंगा StringTranslations
) (फ्रेंच उदाहरण के साथ अपडेट किया गया):
Result
Les APIs
अतिरिक्त वांछित आउटपुट
ऊपर दिए गए उदाहरण को देखते हुए, निम्नलिखित आउटपुट वांछित होगा (फ्रेंच उदाहरण के साथ अद्यतन):
Id Result
0 Billing
1 Les APIs
2 Sales
(हां, मुझे तकनीकी रूप से पता है कि एक स्थिरता के दृष्टिकोण से गलत है, लेकिन यह वही है जो स्थिति में वांछित होगा।)
संपादित करें:
छोटे से अद्यतन, मैंने dbo.Languages
तालिका की संरचना को बदल दिया , और Id (int)
इसे से कॉलम को छोड़ दिया, और इसे बदल दिया Abbreviation
(जिसे अब नाम दिया गया है Id
, और सभी रिश्तेदार फॉरेन-की और और रिश्ते अपडेट किए गए हैं)। एक तकनीकी दृष्टिकोण से, यह इस तथ्य के कारण मेरी राय में अधिक उपयुक्त सेटअप है कि तालिका आईएसओ 639-1 कोडों तक सीमित है, जो कि शुरुआत के लिए अद्वितीय हैं।
Tl, डॉ
तो: सवाल है, मैं कैसे वापसी के लिए इस क्वेरी को संशोधित कर सकता है सब कुछ से SupportCategories
और फिर या तो वापस कर StringTranslations.Text
उस के लिए StringKeys.Id
, Languages.Id
संयोजन, याStringKeys.Name
यह था कि अगर नहीं मौजूद है?
मेरा प्रारंभिक विचार यह है कि मैं किसी अन्य अस्थायी प्रकार के रूप में वर्तमान क्वेरी को किसी अन्य उपकुंजी के रूप में डाल सकता हूं, और इस क्वेरी को अभी तक किसी अन्य SELECT
विवरण में लपेट सकता हूं और उन दो क्षेत्रों का चयन कर सकता हूं जो मैं चाहता हूं ( SupportCategories.Id
और Result
)।
अगर मुझे कुछ नहीं मिलता है, तो मैं बस मानक विधि का उपयोग करता हूं जो मैं आमतौर पर उपयोग करता हूं, जो कि SupportCategories
मेरे सी # प्रोजेक्ट में सभी को लोड करना है, और फिर इसके साथ क्वेरी को चलाने के लिए जो मैंने ऊपर प्रत्येक के खिलाफ मैन्युअल रूप से किया है SupportCategories.Id
।
किसी भी और सभी सुझावों / टिप्पणियों / समालोचना के लिए धन्यवाद।
इसके अलावा, मैं इसके लिए बेतुका रूप से लंबे समय तक माफी मांगता हूं, मैं अभी कोई अस्पष्टता नहीं चाहता हूं। मैं अक्सर StackOverflow पर हूँ और उन सवालों को देखता हूँ जिनमें पदार्थ की कमी है, यहाँ वह गलती करने की इच्छा नहीं थी।