İşte benim senaryom:
Benim bir proje için yerelleştirme üzerinde çalışıyorum ve genellikle benim SQL biraz buff çalışıyorum çünkü ben biraz daha SQL'de bunu yapmak istiyorum, ancak ben C # kodunda bunu hakkında gitmek istiyorum.
Ortam: SQL Server 2014 Standard, C # (.NET 4.5.1)
Not: Programlama dilinin kendisi alakasız olmalı, sadece tamlık için dahil ediyorum.
Bu yüzden istediğimi başardım, ama istediğim ölçüde değil. JOIN
Temel olanlar dışında SQL'ler yaptığımdan beri bir süre (en az bir yıl) oldu ve bu oldukça karmaşık JOIN
.
İşte veritabanının ilgili tablolarının bir diyagramı. (Bu bölüm için çok daha fazlası var, ancak gerekli değil.)
Resimde açıklanan tüm ilişkiler veritabanında tamamlanmıştır - PK
ve FK
kısıtlamaların hepsi kurulum ve işletimdir. Açıklanan sütunların hiçbiri null
mümkün değil. Tüm tabloların şeması vardır dbo
.
Şimdi, neredeyse ne istediğimi yapan bir sorgu var : yani, herhangi bir kimliği SupportCategories
ve herhangi bir kimliği verildi Languages
, ya da dönecektir:
Bu dizi için bu dil (Ie için sağ doğru çeviri varsa StringKeyId
-> StringKeys.Id
var ve içinde LanguageStringTranslations
StringKeyId
, LanguageId
ve StringTranslationId
kombinasyon daha sonra yükler, mevcut StringTranslations.Text
bunun için StringTranslationId
.
Eğer LanguageStringTranslations
StringKeyId
, LanguageId
ve StringTranslationId
kombinasyon vermedi DEĞİL var, o zaman yükler StringKeys.Name
değeri. Languages.Id
Bir verilir integer
.
Sorgu, karışıklık olsun, aşağıdaki gibidir:
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
Sorun şu ki beni sağlama yeteneğine olmadığıdır TÜM ait SupportCategories
ve kendi StringTranslations.Text
varsa, YA onların StringKeys.Name
o olmasaydı. Bunlardan herhangi birini sağlamak mükemmel, ama hiç değil. Temel olarak, bir dilin belirli bir anahtar için çevirisi yoksa, varsayılanın StringKeys.Name
hangisinin StringKeys.DefaultLanguageId
çeviri olduğunu kullanmaktır . (İdeal olarak, bunu bile yapmaz, bunun yerine çeviriyi yükler, bunun yerine StringKeys.DefaultLanguageId
sorgunun geri kalanı için doğru yönde işaret edersem kendim yapabilirim.)
Ben bu konuda çok zaman geçirdim, ve ben sadece C # (genellikle yaptığım gibi) yazacak olsaydı şimdiye kadar yapılacaktı biliyorum. Bunu SQL'de yapmak istiyorum ve sevdiğim çıktıyı almakta sorun yaşıyorum.
Tek uyarı, uygulanan gerçek sorgu sayısını sınırlamak istiyorum. Tüm sütunlar dizine eklenmiştir ve şimdilik onları beğendim ve gerçek stres testi olmadan bunları daha fazla dizine ekleyemiyorum.
Düzenleme: Başka bir not, ben mümkün olduğunca normalleştirilmiş veritabanı tutmak için çalışıyorum, bu yüzden ben önleyebilirsiniz şeyler çoğaltmak istemiyorum.
Örnek Veriler
Kaynak
dbo.SupportCategories (Tamamen):
Id StringKeyId
0 0
1 1
2 2
dbo.Languages (185 kayıt, örnekler için sadece iki tane gösterilmektedir):
Id Abbreviation Family Name Native
38 en Indo-European English English
48 fr Indo-European French français, langue française
dbo.LanguagesStringTranslations (Entirety):
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 (Tamamen):
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 (Entirety):
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
Akım Çıkışı
Aşağıdaki kesin sorgu göz önüne alındığında, çıktı:
Result
Billing
Istenilen çıktı
İdeal olarak, belirli bir şeyi atlamak SupportCategories.Id
ve hepsini elde etmek istiyorum, böylece ( şu anda 38 dilinin English
kullanılıp kullanılmadığına veya 48 French
veya şu anda HERHANGİ başka bir dil kullanılmasına bakılmaksızın ):
Id Result
0 Billing
1 API
2 Sales
Ek Örnek
French
(Ie add ) için bir yerelleştirme eklemek 1 48 8
için LanguageStringTranslations
verildiğinde, çıkış olarak değişecektir (not: bu sadece örnektir, açıkçası yerelleştirilmiş bir dize ekleyeceğim StringTranslations
) (Fransızca örnekle güncellendi):
Result
Les APIs
Ek İstenen Çıktı
Yukarıdaki örnek göz önüne alındığında, aşağıdaki çıktı istenecektir (Fransızca örnekle güncellenmiştir):
Id Result
0 Billing
1 Les APIs
2 Sales
(Evet, teknik olarak bunun tutarlılık açısından yanlış olduğunu biliyorum, ancak bu durumda istenen şey budur.)
Düzenle:
Küçük güncellendi, dbo.Languages
tablonun yapısını değiştirdim ve Id (int)
sütunu ondan bıraktım ve onunla değiştirdim Abbreviation
(şimdi yeniden adlandırıldı Id
ve tüm göreceli Yabancı Anahtarlar ve ve ilişkiler güncellendi). Teknik açıdan bakıldığında, tablonun başlangıçta benzersiz olan ISO 639-1 kodları ile sınırlı olması nedeniyle bu daha uygun bir kurulum.
Tl, Dr.
Yani: Soru, nasıl dönüş için bu sorguyu değiştirebilir şeyi gelen SupportCategories
ve ardından ya dönmek StringTranslations.Text
bunun için StringKeys.Id
, Languages.Id
kombinasyonu, yaStringKeys.Name
da eğer DEĞİL var?
İlk düşüncem, bir şekilde geçerli sorguyu başka bir alt sorgu olarak başka bir geçici sorguya atabiliyor ve bu sorguyu başka bir SELECT
ifadeye sarıp istediğim ( SupportCategories.Id
ve Result
) iki alanı seçebileceğim .
Bir şey bulamazsam, sadece tipik olarak tüm SupportCategories
C # projeme yüklemek için kullandığım standart yöntemi yapacağım ve sonra onunla her birine karşı el ile yukarıdaki sorguyu çalıştırın SupportCategories.Id
.
Her türlü öneri / yorum / eleştiri için teşekkürler.
Ayrıca saçma sapan bir şey olduğu için özür dilerim, herhangi bir belirsizlik istemiyorum. Sık sık StackOverflow üzerinde ve madde eksikliği, burada bu hata yapmak istemiyordu soruları görmek.