Jadi inilah skenario saya:
Saya sedang mengerjakan Pelokalan untuk proyek saya, dan biasanya saya akan melakukan ini dalam kode C #, namun saya ingin melakukan ini dalam SQL sedikit lebih karena saya mencoba sedikit meningkatkan SQL saya.
Lingkungan: SQL Server 2014 Standard, C # (.NET 4.5.1)
Catatan: bahasa pemrograman itu sendiri seharusnya tidak relevan, saya hanya memasukkannya untuk kelengkapan.
Jadi saya semacam mencapai apa yang saya inginkan, tetapi tidak sejauh yang saya inginkan. Sudah lama (setidaknya satu tahun) sejak saya melakukan SQL JOINkecuali yang dasar, dan ini cukup kompleks JOIN.
Berikut adalah diagram dari tabel-tabel basis data yang relevan. (Ada banyak lagi, tetapi tidak perlu untuk porsi ini.)

Semua hubungan yang dijelaskan dalam gambar lengkap dalam database - PKdan FKsemua kendala adalah pengaturan dan operasi. Tak satu pun dari kolom yang dijelaskan nullmampu. Semua tabel memiliki skema dbo.
Sekarang, saya punya pertanyaan yang hampir tidak apa yang saya inginkan: yang, diberikan APAPUN Id dari SupportCategoriesdan APAPUN Id dari Languages, itu akan kembali baik:
Jika ada terjemahan yang tepat-tepat untuk bahasa yang untuk string yang (Ie StringKeyId-> StringKeys.Idada, dan dalam LanguageStringTranslations StringKeyId, LanguageIddan StringTranslationIdkombinasi ada, maka beban StringTranslations.Textuntuk itu StringTranslationId.
Jika LanguageStringTranslations StringKeyId, LanguageId, dan StringTranslationIdkombinasi itu tidak ada, maka beban StringKeys.Namenilai. Itu Languages.Iddiberikan integer.
Permintaan saya, baik berantakan, adalah sebagai berikut:
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
Masalahnya adalah bahwa hal itu tidak mampu memberikan saya semua dari SupportCategoriesdan masing-masing StringTranslations.Textjika ada, OR mereka StringKeys.Namejika tidak ada. Ini sempurna dalam menyediakan salah satu dari mereka, tetapi tidak sama sekali. Pada dasarnya, itu untuk menegakkan bahwa jika bahasa tidak memiliki terjemahan untuk kunci tertentu, maka default adalah menggunakan StringKeys.Nameyang dari StringKeys.DefaultLanguageIdterjemahan. (Idealnya, itu bahkan tidak akan melakukan itu, tetapi malah memuat terjemahan untuk StringKeys.DefaultLanguageId, yang bisa saya lakukan sendiri jika menunjuk ke arah yang benar untuk sisa permintaan.)
Saya telah menghabiskan banyak waktu untuk hal ini, dan saya tahu jika saya hanya menulisnya dalam C # (seperti biasanya saya lakukan) itu akan dilakukan sekarang. Saya ingin melakukan ini dalam SQL, dan saya mengalami kesulitan mendapatkan output yang saya suka.
Satu-satunya peringatan, adalah saya ingin membatasi jumlah permintaan aktual yang diterapkan. Semua kolom diindeks dan seperti saya suka untuk saat ini, dan tanpa pengujian stres nyata saya tidak dapat mengindeks lebih lanjut.
Sunting: Catatan lain, saya mencoba untuk menjaga database agar senormalisasi mungkin, jadi saya tidak ingin menduplikasi hal-hal jika saya bisa menghindarinya.
Contoh Data
Sumber
dbo.SupportCategories (Entirety):
Id StringKeyId
0 0
1 1
2 2
dbo.Languages (185 catatan, hanya menampilkan dua untuk contoh):
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 (Entirety):
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
Output Saat Ini
Dengan kueri persis di bawah, ini menghasilkan:
Result
Billing
Output yang Diinginkan
Idealnya, saya ingin menghilangkan yang spesifik SupportCategories.Id, dan mendapatkan semuanya, seperti itu (terlepas dari apakah bahasa 38 Englishdigunakan, atau 48 French, atau APA SAJA bahasa lain saat ini):
Id Result
0 Billing
1 API
2 Sales
Contoh tambahan
Mengingat saya menambahkan lokalisasi untuk French(Yaitu menambahkan 1 48 8ke LanguageStringTranslations), output akan berubah menjadi (catatan: ini adalah contoh saja, jelas saya akan menambahkan string terlokalisasi ke StringTranslations) (diperbarui dengan contoh Prancis):
Result
Les APIs
Output yang Diinginkan Tambahan
Diberikan contoh di atas, output berikut akan diinginkan (diperbarui dengan contoh Prancis):
Id Result
0 Billing
1 Les APIs
2 Sales
(Ya, saya tahu secara teknis itu salah dari sudut pandang konsistensi, tetapi itulah yang diinginkan dalam situasi tersebut.)
Edit:
Kecil diperbarui, saya memang mengubah struktur dbo.Languagestabel, dan menjatuhkan Id (int)kolom dari itu, dan menggantinya dengan Abbreviation(yang sekarang diganti namanya menjadi Id, dan semua kunci asing relatif dan dan hubungan diperbarui). Dari sudut pandang teknis, ini adalah pengaturan yang lebih tepat menurut saya karena tabel tersebut terbatas pada kode ISO 639-1, yang unik untuk memulai.
Tl; dr
Jadi: pertanyaannya, bagaimana bisa saya memodifikasi query ini untuk kembali segala sesuatu dari SupportCategoriesdan kemudian kembali baik StringTranslations.Textuntuk itu StringKeys.Id, Languages.Idkombinasi, atau yang StringKeys.Namejika hal itu tidak ada?
Pikiran awal saya, adalah bahwa saya entah bagaimana bisa mengirimkan kueri saat ini ke jenis sementara lain sebagai subquery lain, dan membungkus kueri ini dalam SELECTpernyataan lain dan memilih dua bidang yang saya inginkan ( SupportCategories.Iddan Result).
Jika saya tidak menemukan apa-apa, saya hanya akan melakukan metode standar yang biasanya saya gunakan yaitu untuk memuat semua SupportCategorieske dalam proyek C # saya, dan kemudian menjalankan query yang saya miliki di atas secara manual terhadap masing-masing SupportCategories.Id.
Terima kasih atas semua dan semua saran / komentar / kritik.
Juga, saya minta maaf karena terlalu panjang, saya hanya tidak ingin ambiguitas. Saya sering berada di StackOverflow dan melihat pertanyaan yang tidak memiliki substansi, tidak ingin membuat kesalahan itu di sini.
