So erhalten Sie Text für die Standardsprache
-
16-10-2019 - |
Frage
Ich habe so Tische:
und so Daten in der Sprache Tabelle:
und so Daten in der Texttabelle:
Ich muss Text für zurückgeben angefordert Sprache, wenn es existiert und Text für Ursprünglich Sprache, wenn es tut nicht existieren. Ist es möglich, das in zu tun? eines Abfrage (Nr while
, bitte)?
Code:
DECLARE @CommentId bigint = 1
--DECLARE @LanguageCode nvarchar(2) = 'en' -- "english text" returns
DECLARE @LanguageCode nvarchar(2) = 'ua' -- nothing at this moment
SELECT
t.CommentId
,t.TextId
,t.[Text]
,t.LanguageId
,RequestedLanguageId = @LanguageCode
FROM dbo.common_Text t
INNER JOIN dbo.common_LanguageType l
ON t.LanguageId = l.LanguageId
WHERE l.Code = @LanguageCode
AND t.CommentId = @CommentId
Vielen Dank.
HINZUGEFÜGT:
Wenn Code einen Text in 'ua' (ukrainisch) anfordert und dies kein Text für diese Sprache ist, wird er den Text nach Russisch suchen. Wenn gefunden - ok, wenn es nicht nach einem Text für Englisch sucht. Die Liste der Sprachen kann variieren.
Lösung
Mit einem rekursiven CTE erstellt diese Abfrage eine Tabelle aller Sprachen, die irgendwo in ihrer Standardkette auf eine Sprache zeigen, die den erforderlichen Kommentar enthält. Es zeigt jede Sprache neben ihrem ersten Standard, der den erforderlichen Kommentar enthält. Anschließend filtert diese Tabelle, um Ihnen den ersten verfügbaren Text für die von Ihnen ausgewählte Sprache zu geben.
DECLARE @CommentId BIGINT = 1;
DECLARE @LanguageCode NVARCHAR(2) = 'en';
WITH languages AS (
-- base case: language has required comment
SELECT
lt.LanguageId AS RootLanguageId
, lt.LanguageId
, lt.Code
, lt.DefaultId
, 0 AS Level
FROM
dbo.common_LanguageType lt
--WHERE
-- lt.LanguageId = lt.DefaultId
WHERE
EXISTS (
SELECT *
FROM dbo.common_Text t
WHERE
t.CommentId = @CommentId
AND t.LanguageId = lt.LanguageId
)
UNION ALL
-- recursive case: language is not its own default and
-- does not have the required comment
SELECT
l_default.RootLanguageId
, l.LanguageId
, l.Code
, l.DefaultId
, l_default.Level + 1 AS Level
FROM
dbo.common_LanguageType l
INNER JOIN languages l_default
ON l.DefaultId = l_default.LanguageId
WHERE
l.LanguageId <> l.DefaultId
AND NOT EXISTS (
SELECT *
FROM dbo.common_Text t
WHERE
t.CommentId = @CommentId
AND t.LanguageId = l.LanguageId
)
)
SELECT t.Text
FROM
languages l
INNER JOIN dbo.common_Text t
ON l.RootLanguageId = t.LanguageId
WHERE
l.Code = @LanguageCode
;
Versuchen Sie einfach zu rennen
SELECT *
FROM languages;
Wenn Sie ein Gefühl für das bekommen möchten, was der rekursive CTE tut. Ich habe ein Skript hochgeladen, um die Tabellen zu erstellen, einige Beispieldaten einzufügen und den obigen Code auszuführen zu gist.
Ziemlich sexy, nein?