0
votes

SQL Sélectionnez avec conditionnel où la clause

Abstrait:

J'ai une requête sélectionnée avec une condition où je aimerait d'avoir rencontré. Dans certains cas, là où la condition ne sera pas remplie et dans de tels cas, j'aimerais utiliser une autre condition. C'est le problème abstrait que je suis confronté. Voici un exemple plus spécifique:

Exemple:

J'ai une balise table et un tag_l11n table. La table d'étiquette contient des informations de base sur une balise et la table tag_l11n contient le nom localisé de la balise. Dans le Select simplifié suivant, je demande la balise avec un nom anglais ( tag_l11n_language = 'fr' )

< Pré> xxx

problème:

Le problème commence si une balise n'a pas de traduction. Par exemple, une balise peut exister en langue anglaise mais non par ex. Langue italienne. Cependant, le gars italien accepterait également les étiquettes en langue anglaise (ou toute autre langue) iff (si et seulement si) la traduction italienne n'existe pas.

dans le fin je préférerais une solution dans laquelle je pourrais spécifier différentes priorités (1. Localisation de l'utilisateur, 2. Anglais, 3. Toute autre langue).

Je suis un peu à perte ici. Bien que je puisse facilement omettre la condition (langage = ??) et filtrer le résultat pendant la sortie / la présentation, je ne pense pas que c'est la voie à suivre.


4 commentaires

Fournir des échantillons de données et une sortie attendue sous forme tabulaire.


En d'autres termes - si la requête ci-dessus avec la condition tag_l11n_2`.``tag_l11n_language` = "fr ' ne renvoie pas de lignes, alors faites une autre - presque la même requête mais avec condition tag_l11n_2 . tag_l11n_language <> 'en'``` est-ce correct?


Voir meta.stackoverflow.com/questions/333952/...


@krokodilko correct


4 Réponses :


5
votes

Vous pouvez ajouter une clause à votre qui retournera une traduction en anglais si la traduction italienne n'existait pas, à l'aide d'un n'existe pas Clause: XXX

Un autre (éventuellement plus performant donné, il ne disposera pas d'une solution ou condition) serait de rejoindre à tag_l11n_2 deux fois, une fois pour la langue souhaitée, et une fois pour la sauvegarde, et utilisez coalesce pour hiérartir le résultat des langages souhaité: xxx

note que cela peut Soyez étendu à autant de langages de sauvegarde que ceux souhaités en ajoutant rejoindre S et les colonnes appropriées sur le coalesce .

Démo (des deux requêtes) sur dbfiddle


4 commentaires

Je n'ai pas répondu, mais ou Les conditions de participation ont généralement un mauvais plan. De plus, cette logique est difficile à prolonger si vous souhaitez ajouter une autre langue, par exemple. Ceci toute autre langue


@Dnoeth vous soulevez un bon point; J'ai édité la réponse avec une requête alternative qui serait probablement plus performante. Votre approche utilisant l'agrégation est également bonne.


@Denniseichhorn Veuillez noter que j'ai édité ma réponse avec une requête qui peut être plus performante que l'original. Aussi, j'ai ajouté une petite démonstration des deux requêtes.


@Nick merci. J'ai également modifié une version où je pourrais avoir une autre langue si aucun des précédents correspondants. dbfiddle.uk/...



2
votes

Si vous exécutez MySQL 8.0, je recommanderais Row_Number () pour gérer la priorisation: xxx

avec cette solution, vous pouvez gérer autant de niveaux de Prix ​​de la priorisation tel que recherché, en ajoutant plus de conditions à la clause par de Row_Number () . Actuellement, cela met la traduction italienne d'abord, suivie de la traduction anglaise, suivie de toute autre traduction disponible (alphabétiquement-wise).


1 commentaires

Bon à savoir, je n'ai pas mysql 8 mais je garderai ça à l'esprit pour l'avenir car il semble vraiment puissant.



1
votes

Votre condition change la gauche sur une jointure interne, ce qui n'a entraîné aucune ligne renvoyée lorsqu'il n'y a pas de rangée pour EN code>.

La solution classique utilise une langue de joint à gauche, puis coalez pour obtenir la première valeur non nulle: p> xxx pré>

tandis que la solution de GMB fonctionne sans langue par défaut, cette solution nécessite une valeur par défaut (la langue sans traduction manquante), dans votre cas probablement de code> :-) p>

La requête de GMB peut-être améliorée en appliquant Row_Number avant em> le REJOIGNEZ: P>

SELECT tag_id_3, tag_l11n_title_2
FROM `tag` as t
LEFT JOIN -- INNER JOIN should be possible
 (
    SELECT 
        `tag_l11n_tag` as tag_id_3,
        COALESCE(MAX(CASE WHEN `tag_l11n_language` = 'it' THEN `tag_l11n_title` END)
                ,MAX(CASE WHEN `tag_l11n_language` = 'en' THEN `tag_l11n_title` END)
                ,MAX(CASE WHEN `tag_l11n_language` = 'de' THEN `tag_l11n_title` END)
                -- if there's no default you can get a random value using ,MAX(`tag_l11n_title`)
                ) AS tag_l11n_title_2
    FROM `tag_l11n`
    GROUP BY `tag_l11n_tag`
  ) AS t1
ON t.`tag_id` = tl.`tag_l11n_tag` 
ORDER BY t.`tag_id`
LIMIT 25; -- might be possible to move into Derived Table


0 commentaires

0
votes

Merci à @nick Réponse, j'ai proposé une nouvelle idée pour utiliser la fonction champ () code> qui couvrirait toutes les langues possibles sans rejoindre une table séparée pour chaque langue, mais avec un seul sous-sélection. Je ne suis pas sûr de la performance comparant les autres réponses, mais ce serait plus rapide si les langues sont indexées par des valeurs numériques que des chaînes ( fr code>, it code> etc.). Bien sûr, les traductions avec NULL doivent être exclues dans le sous-sélection. P>

SELECT 
    `tag`.`tag_id` as tag_id,
    COALESCE(`tag_l11n`.`tag_l11n_title`,"No translation") as tag_l11n_title
FROM 
    `tag` as tag
LEFT JOIN (
      SELECT
          `tag_l11n_tag` as tag_id,
          `tag_l11n_title` as tag_l11n_title,
      FROM 
          `tag_l11n`
      WHERE 
          `tag_l11n_title` IS NOT NULL,
      ORDER BY
          FIELD(`tag_l11n_language`,"it","en","es")
      LIMIT 1
      ) as tag_l11n ON `tag_l11n`.`tag_id` = `tag`.`tag_id`
ORDER BY 
    `tag`.`tag_id` ASC 


1 commentaires

Outre les fautes de frappe, cela ne donnera que donner un résultat pour la première valeur de la balise Tableau: dbfiddle.uk/...