Vì vậy, đây là kịch bản của tôi:
Tôi đang làm việc về Bản địa hóa cho một dự án của tôi và thông thường tôi sẽ thực hiện việc này trong mã C #, tuy nhiên tôi muốn làm điều này trong SQL thêm một chút vì tôi đang cố gắng nâng cấp SQL của mình một chút.
Môi trường: Tiêu chuẩn SQL Server 2014, C # (.NET 4.5.1)
Lưu ý: bản thân ngôn ngữ lập trình không liên quan, tôi chỉ bao gồm nó để hoàn thiện.
Vì vậy, tôi sắp xếp hoàn thành những gì tôi muốn, nhưng không đến mức tôi muốn. Đã được một thời gian (ít nhất là một năm) kể từ khi tôi thực hiện bất kỳ SQL nào JOINngoại trừ những SQL cơ bản và điều này khá phức tạp JOIN.
Dưới đây là sơ đồ của các bảng có liên quan của cơ sở dữ liệu. (Có nhiều hơn nữa, nhưng không cần thiết cho phần này.)

Tất cả các mối quan hệ được mô tả trong hình ảnh đều hoàn chỉnh trong cơ sở dữ liệu - các ràng buộc PKvà FKtất cả đều được thiết lập và vận hành. Không có cột nào được mô tả là nullcó thể. Tất cả các bảng có lược đồ dbo.
Bây giờ, tôi có một truy vấn gần như thực hiện những gì tôi muốn: đó là, đưa ra BẤT K Id Id nào SupportCategoriesvà BẤT K Id Id nào Languages, nó sẽ trả về:
Nếu có một bản dịch phải thích hợp cho rằng ngôn ngữ cho chuỗi (Ie StringKeyId-> StringKeys.Idtồn tại, và trong LanguageStringTranslations StringKeyId, LanguageIdvà StringTranslationIdkết hợp tồn tại, sau đó nó tải StringTranslations.Textcho rằng StringTranslationId.
Nếu LanguageStringTranslations StringKeyId, LanguageIdvà StringTranslationIdsự kết hợp đã không tồn tại, sau đó nó tải các StringKeys.Namegiá trị. Đây Languages.Idlà một cho trước integer.
Truy vấn của tôi, có thể là một mớ hỗn độn, như sau:
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
Vấn đề là nó không có khả năng cung cấp cho tôi TẤT CẢ của SupportCategoriesvà của mình StringTranslations.Textnếu nó tồn tại, HOẶC họ StringKeys.Namenếu nó không tồn tại. Nó là hoàn hảo trong việc cung cấp bất kỳ một trong số họ, nhưng không phải là tất cả. Về cơ bản, cần phải thực thi rằng nếu một ngôn ngữ không có bản dịch cho một khóa cụ thể, thì mặc định là sử dụng bản dịch StringKeys.Nameđó là StringKeys.DefaultLanguageIdbản dịch. (Lý tưởng nhất là nó thậm chí sẽ không làm điều đó, mà thay vào đó hãy tải bản dịch cho StringKeys.DefaultLanguageIdcái mà tôi có thể tự làm nếu được chỉ đúng hướng cho phần còn lại của truy vấn.)
Tôi đã dành rất nhiều thời gian cho việc này và tôi biết nếu tôi chỉ viết nó bằng C # (như tôi thường làm) thì bây giờ nó sẽ được thực hiện. Tôi muốn làm điều này trong SQL và tôi gặp khó khăn khi nhận đầu ra mà tôi thích.
Nhắc nhở duy nhất, là tôi muốn giới hạn số lượng truy vấn thực tế được áp dụng. Tất cả các cột được lập chỉ mục và như tôi thích chúng bây giờ và không có kiểm tra căng thẳng thực sự, tôi không thể lập chỉ mục cho chúng thêm.
Chỉnh sửa: Một lưu ý khác, tôi đang cố gắng giữ cơ sở dữ liệu bình thường nhất có thể, vì vậy tôi không muốn sao chép mọi thứ nếu tôi có thể tránh được.
Dữ liệu mẫu
Nguồn
dbo.SupportC loại (Entirety):
Id StringKeyId
0 0
1 1
2 2
dbo. Ngôn ngữ (185 bản ghi, chỉ hiển thị hai ví dụ):
Id Abbreviation Family Name Native
38 en Indo-European English English
48 fr Indo-European French français, langue française
dbo.LacularStringTranslations (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 (Toàn bộ):
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
Sản lượng hiện tại
Đưa ra truy vấn chính xác dưới đây, nó xuất ra:
Result
Billing
Kết quả mong muốn
Lý tưởng nhất, tôi muốn có thể bỏ qua phần cụ thể SupportCategories.Idvà nhận tất cả chúng, như vậy (bất kể ngôn ngữ 38 Englishđã được sử dụng hay 48 Frenchhoặc BẤT K Language ngôn ngữ nào khác vào lúc này):
Id Result
0 Billing
1 API
2 Sales
Ví dụ bổ sung
Nếu tôi đã thêm một bản địa hóa cho French(Ie add 1 48 8to LanguageStringTranslations), đầu ra sẽ thay đổi thành (lưu ý: đây chỉ là ví dụ, rõ ràng tôi sẽ thêm một chuỗi nội địa hóa vào StringTranslations) (cập nhật với ví dụ tiếng Pháp):
Result
Les APIs
Đầu ra mong muốn bổ sung
Cho ví dụ trên, đầu ra sau đây sẽ được mong muốn (cập nhật với ví dụ bằng tiếng Pháp):
Id Result
0 Billing
1 Les APIs
2 Sales
(Vâng, tôi biết về mặt kỹ thuật đó là sai từ quan điểm nhất quán, nhưng đó là điều sẽ được mong muốn trong tình huống này.)
Chỉnh sửa:
Được cập nhật nhỏ, tôi đã thay đổi cấu trúc của dbo.Languagesbảng và thả Id (int)cột khỏi nó và thay thế nó bằng Abbreviation(hiện được đổi tên thành Id, và tất cả các Khóa ngoài và các mối quan hệ được cập nhật). Theo quan điểm kỹ thuật, đây là một thiết lập phù hợp hơn theo quan điểm của tôi do thực tế là bảng được giới hạn ở các mã ISO 639-1, là duy nhất để bắt đầu.
Tl; dr
Vì vậy: các câu hỏi, làm thế nào có thể tôi sửa đổi truy vấn này để trả lại tất cả mọi thứ từ SupportCategoriesvà sau đó trở về hoặc là StringTranslations.Textcho rằng StringKeys.Id, Languages.Idsự kết hợp, hoặc những StringKeys.Namenếu nó đã không tồn tại?
Suy nghĩ ban đầu của tôi, là bằng cách nào đó tôi có thể chuyển truy vấn hiện tại sang một loại tạm thời khác như một truy vấn con khác và bọc truy vấn này trong một SELECTcâu lệnh khác và chọn hai trường tôi muốn ( SupportCategories.Idvà Result).
Nếu tôi không tìm thấy bất cứ điều gì, tôi sẽ chỉ thực hiện phương pháp tiêu chuẩn mà tôi thường sử dụng đó là tải tất cả SupportCategoriesvào dự án C # của mình, và sau đó với nó chạy truy vấn tôi có ở trên theo cách thủ công SupportCategories.Id.
Cảm ơn cho bất kỳ và tất cả các đề xuất / ý kiến / phê bình.
Ngoài ra, tôi xin lỗi vì nó quá dài một cách vô lý, tôi chỉ không muốn bất kỳ sự mơ hồ nào. Tôi thường xuyên vào StackOverflow và thấy những câu hỏi thiếu chất, không muốn mắc lỗi ở đây.
