ดังนั้นนี่คือสถานการณ์ของฉัน:
ฉันทำงาน Localization สำหรับโครงการของฉันและโดยทั่วไปฉันจะทำเช่นนี้ในรหัส C # แต่ฉันต้องการทำเช่นนี้ใน SQL อีกเล็กน้อยตั้งแต่ฉันพยายามควัก SQL เล็กน้อย
สภาพแวดล้อม: มาตรฐาน SQL Server 2014, C # (.NET 4.5.1)
หมายเหตุ: ภาษาการเขียนโปรแกรมควรไม่เกี่ยวข้องฉันเพียง แต่รวมไว้เพื่อความสมบูรณ์เท่านั้น
ดังนั้นฉันจึงประสบความสำเร็จในสิ่งที่ฉันต้องการ แต่ไม่เท่าที่ฉันต้องการ จะได้รับในขณะที่ (อย่างน้อยปี) ตั้งแต่ผมได้กระทำใด ๆ SQL JOIN
s JOIN
ยกเว้นคนพื้นฐานและนี้ค่อนข้างซับซ้อน
นี่คือ diagramme ของตารางที่เกี่ยวข้องของฐานข้อมูล (มีอีกมากมาย แต่ไม่จำเป็นสำหรับส่วนนี้)
ความสัมพันธ์ทั้งหมดที่อธิบายในภาพเสร็จสมบูรณ์ในฐานข้อมูล - 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
ซึ่งฉันสามารถทำเองได้หากชี้ไปในทิศทางที่ถูกต้องสำหรับส่วนที่เหลือของการค้นหา)
ฉันใช้เวลาไปมากกับเรื่องนี้และฉันรู้ว่าถ้าฉันจะเขียนมันใน C # (เหมือนที่ฉันทำตามปกติ) ตอนนี้จะเสร็จแล้ว ฉันต้องการทำสิ่งนี้ใน SQL และฉันมีปัญหาในการรับผลลัพธ์ที่ฉันชอบ
ข้อแม้เดียวคือฉันต้องการ จำกัด จำนวนการค้นหาจริงที่ใช้ คอลัมน์ทั้งหมดได้รับการจัดทำดัชนีและอย่างที่ฉันชอบในตอนนี้และหากไม่มีการทดสอบความเครียดจริง ๆ ฉันก็ไม่สามารถจัดทำดัชนีต่อไปได้
แก้ไข: บันทึกย่ออื่นฉันกำลังพยายามทำให้ฐานข้อมูลเป็นปกติที่สุดเท่าที่จะทำได้ดังนั้นฉันไม่ต้องการทำซ้ำสิ่งต่าง ๆ หากฉันสามารถหลีกเลี่ยงได้
ตัวอย่างข้อมูล
แหล่ง
dbo. สนับสนุนหมวดหมู่ (ทั้งหมด):
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.LanguageStringTranslations (ทั้งหมด):
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
และทั้งหมด Foreign-Keys และสัมพัทธ์และความสัมพันธ์ที่อัปเดตแล้ว) จากมุมมองทางเทคนิคนี่คือการตั้งค่าที่เหมาะสมมากขึ้นในความคิดของฉันเนื่องจากความจริงที่ว่าตารางนั้น จำกัด รหัส ISO 639-1 ซึ่งไม่เหมือนใครในการเริ่มต้น
tl; DR
ดังนั้น: คำถามที่ว่าฉันจะปรับเปลี่ยนแบบสอบถามนี้เพื่อกลับมาทุกอย่างจากSupportCategories
นั้นกลับอย่างใดอย่างหนึ่งStringTranslations.Text
ที่StringKeys.Id
, Languages.Id
รวมหรือStringKeys.Name
ถ้ามันไม่ไม่อยู่?
ความคิดเริ่มต้นของฉันคือว่าฉันสามารถส่งแบบสอบถามปัจจุบันไปยังอีกประเภทชั่วคราวเป็นแบบสอบถามย่อยอื่นและตัดแบบสอบถามนี้ในSELECT
งบอื่นและเลือกสองเขตข้อมูลที่ฉันต้องการ ( SupportCategories.Id
และResult
)
ถ้าฉันไม่ได้พบสิ่งที่ฉันจะทำวิธีการมาตรฐานที่ผมมักจะใช้ซึ่งก็คือการโหลดทั้งหมดSupportCategories
ในโครงการของฉัน C # SupportCategories.Id
แล้วกับมันเรียกใช้แบบสอบถามฉันมีดังกล่าวข้างต้นด้วยตนเองกับแต่ละ
ขอบคุณสำหรับคำแนะนำ / ความคิดเห็น / คำวิจารณ์ใด ๆ และทั้งหมด
นอกจากนี้ฉันต้องขอโทษด้วยที่มันนานมากฉันแค่ไม่ต้องการความคลุมเครือ ฉันมักจะอยู่ใน StackOverflow และดูคำถามที่ไม่มีเนื้อหาไม่ต้องการทำผิดพลาดที่นี่