T-SQL, где утверждение - ИЛИ
Извините за смутное название, но я действительно не знал, какое название дать этой проблеме:
У меня есть следующий набор результатов:
ID Field FieldValue Culture
1 Color Groen nl-NL
2 Taste Kip nl-NL
3 Color Green en-GB
4 Taste Chicken en-GB
5 Color Green en
6 Taste Chicken en
Я хотел бы подражать ASP.Net способ выбора ресурса, культура пользователя (nl-NL)
SELECT Field, FieldValue FROM Tbl WHERE Culture = 'nl-NL'
Или когда нет результатов для конкретной культуры, попробуйте родительскую культуру (nl)
SELECT Field, FieldValue FROM Tbl WHERE Culture = 'nl'
Или если нет результатов для родительской культуры, попробуйте стандартную Культуру (en)
SELECT Field, FieldValue FROM Tbl WHERE Culture = 'en'
Как я могу объединить эти операторы SELECT в один оператор T-SQL?
Я использую LINQ, чтобы выражение LINQ было бы еще лучше.
Оператор OR не сработает, потому что я не хочу смешивать разные культуры.
Оператор ORDER BY не поможет, потому что он возвращает несколько записей для каждой культуры.
Вывод может выглядеть следующим образом (nl-NL):
Color Groen
Taste Kip
или (en-GB / en):
Color Green
Taste Chicken
5 ответов
Итак, вот код, который делает именно то, что написано в вашем примере. Ожидается, что вы определите конкретную культуру (nl-NL), нейтральную культуру (nl) и запасную культуру (en) в коде на стороне клиента и передадите эти значения в SQL.
SELECT Field, FieldValue FROM Tbl WHERE Culture = (
SELECT TOP 1 Culture FROM (
SELECT 1 as n, Culture FROM Tbl WHERE Culture = 'nl-NL'
UNION
SELECT 2, Culture FROM Tbl WHERE Culture = 'nl'
UNION
SELECT 3, Culture FROM Tbl WHERE Culture = 'en'
) cultures
ORDER BY n
)
Вы уверены, что вам нужна вся таблица перевода для данной культуры, а не перевод каждой строки? Что если у вас есть строки A и B в en, но только строка A в nl-NL?
Попробуй это:
SELECT Field, FieldValue FROM Tbl WHERE Culture = 'nl-NL'
union
SELECT Field, FieldValue FROM Tbl WHERE Culture = 'nl'
and not exists(select * from tbl where culture = 'nl-NL')
union
SELECT Field, FieldValue FROM Tbl WHERE Culture = 'en'
and not exists(select * from tbl where culture = 'nl-NL')
and not exists(select * from tbl where culture = 'nl')
Linq:
var x = (from a in tbl
where culture == "nl-NL"
select a
)
.Union
(from a in tbl
where culture == "nl"
&& !tbl.Any(c => c.Culture == "nl-NL")
select a
)
.Union
(from a in tbl
where culture == "en"
&& !tbl.Any(c => c.Culture == "nl-NL")
&& !tbl.Any(c => c.Culture == "nl")
select a
);
Предполагая, что культура передается в @Culture:
select Field,COALESCE(fc.FieldValue,pc.FieldValue,dc.FieldValue)
from
Tbl dc
left join
Tbl pc
on
dc.Field = pc.Field and
pc.Culture = SUBSTRING(@Culture,1,CHARINDEX('-',@Culture)-1)
left join
Tbl fc
on
dc.Field = fc.Field and
fc.Culture = @Culture
where
dc.Culture = 'en'
вернет всю таблицу (псевдонимы могут быть длиннее - dc = культура по умолчанию, pc = частичная культура, fc = полная культура.
Учитывая целевую культуру, верните либо полное совпадение, либо неудачное совпадение с родителем. (Предполагается, что осталось 2 персонажа из поля Культура)
(ОБНОВЛЕНО)
-- @TargetCulture represents the culture we are interested in
DECLARE @TargetCulture varchar(5)
SET @TargetCulture = 'nl-NL'
-- Parent represents the Result_Set (as in OP) plus column for the 'parent' culture
;WITH Parent AS
(
SELECT
*,
LEFT(Culture, 2) AS parent
FROM
Result_Set
)
SELECT
*
FROM
Parent
WHERE
-- Get either a full matching culture or just a match on the parent
(@TargetCulture = Culture AND @TargetCulture <> parent)
OR
(@TargetCulture <> Culture AND @TargetCulture = parent)
Измените значение @TargetCulture
переменная для получения данных о культуре nl
, en-GB
, а также en
,
Другой метод;
SELECT * FROM tbl WHERE tbl.Culture = (
SELECT COALESCE(
CASE WHEN EXISTS (SELECT 1 FROM tbl WHERE Culture = @locale) THEN @locale ELSE NULL END,
CASE WHEN EXISTS (SELECT 1 FROM tbl WHERE Culture = SUBSTRING(@locale, 1, CHARINDEX('-', @locale + '-') - 1)) THEN SUBSTRING(@locale, 1, CHARINDEX('-', @locale + '-') - 1) ELSE NULL END,
'en'
)
)
nl-nl -> 'nl-nl'
en -> 'en'
en-xxx -> 'en'
zz-gg -> 'en'
en-gb -> 'en-gb'
ff -> 'en'