2010-04-20 8 views
2

Désolé pour le titre vague, mais je ne savais vraiment pas ce titre à donner à ce problème:T-SQL Où déclaration - OU

je l'ensemble de résultat suivant:

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 

Je voudrais comme pour imiter la façon dont ASP.Net de sélection des ressources, la culture de l'utilisateur (nl-NL)

SELECT Field, FieldValue FROM Tbl WHERE Culture = 'nl-NL' 

Ou quand il n'y a pas de résultats pour la culture spécifique, essayez la culture mère (nl)

SELECT Field, FieldValue FROM Tbl WHERE Culture = 'nl' 

Ou quand il n'y a pas de résultats pour la culture mère, essayez la valeur par défaut Culture (en)

SELECT Field, FieldValue FROM Tbl WHERE Culture = 'en' 

Comment puis-je combiner ces SELECT déclarations dans une instruction T-SQL?
J'utilise LINQ donc une expression LINQ serait encore plus grande.

L'instruction OR ne fonctionnera pas, car je ne veux pas un mélange de cultures.
L'instruction ORDER BY- n'aidera pas, car elle renvoie plusieurs enregistrements par culture.

La sortie pourrait ressembler à (nl-NL):

Color Groen 
Taste Kip 

ou (en-GB/fr):

Color Green 
Taste Chicken 
+0

Quelle est votre sortie désirée alors? Essayez-vous d'implémenter une solution de remplacement dans laquelle une chaîne n'a pas été traduite dans les paramètres régionaux préférés? (Si oui, vous auriez besoin d'une sorte d'id pour attacher des chaînes équivalentes) –

+0

Que faire si la langue que vous demandez a des valeurs mais pas toutes? Par exemple, si nl-NL inclut une valeur pour le goût, mais n'inclut pas de valeur pour la couleur, avez-vous besoin de retourner le goût nl-NL * et * la valeur de repli nl pour la couleur? Et mangez-vous vraiment du poulet vert aux Pays-Bas? – Ray

+0

@Zyphrax: chaque culture a-t-elle son propre ensemble complet de champs et de paires de valeurs? c'est-à-dire que si la culture ** en ** a une paire de valeurs de champ qui forme une entrée de forme, cercle, le reste de la langue aura sa propre paire valeur de champ de forme, cercle? –

Répondre

4

Alors, est le code ici qui fait exactement ce qui est écrit dans votre exemple. On s'attend à ce que vous déterminiez la culture spécifique (nl-NL), la culture neutre (nl) et la culture de repli (en) dans le code côté client et alimentez ces valeurs à SQL. Etes-vous sûr que vous avez besoin de toute la table de traduction pour une culture donnée, pas une traduction de chaque chaîne? Que faire si vous avez la chaîne A et B dans en, mais seulement la chaîne A dans nl-NL?

1

En supposant la culture est transmis dans à @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' 

retourne la table entière (alias pourrait être plus - dc = culture par défaut, pc = culture partielle, fc = culture pleine

.
2

Essayez ceci:

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 
     ); 
+0

Les instructions EXISTS dans le SQL ne semblent pas correctes. De la façon dont ceci se lit, s'il y a des lignes reçues dans le premier SELECT, rien d'autre ne sera ajouté dans l'UNION. Je pense que c'est la bonne approche, mais les sous-requêtes doivent être corrélées avec les lignes sélectionnées des requêtes principales. –

+0

Cela fonctionne et n'est pas tributaire de l'ordre. Il n'a pas besoin d'être corrélé, il suffit de tester (en utilisant EXISTS) s'il y a des enregistrements qui sont mutuellement incompatibles avec la condition principale de WHERE. La construction EXISTS n'a pas besoin d'être corrélée à la requête principale, c'est une construction valide: AND EXIST (SELECT 1) –

+0

Je ne voulais pas dire qu'elle dépend de l'ordre ou que la construction n'était pas SQL valide. Ce que je voulais dire, c'est que si le premier select renvoie des données, alors les NOT EXISTS dans les deuxième et troisième sélections retourneront false pour chaque ligne, et aucune donnée ne sera retournée. –

0

Étant donné une culture cible, renvoyez la correspondance complète ou, à défaut, une correspondance sur le parent. (Supposé être la gauche 2 caractères du champ Culture)

(MIS À JOUR)

-- @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) 

Changer la valeur de la variable @TargetCulture pour récupérer des données de culture pour nl, en-GB et en.

0

Une autre méthode;

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' 
Questions connexes