2011-02-21 4 views
5

Je suis confronté à la situation suivante.Tri complexe sur base de données MySQL

Nous avons un CMS avec une entité avec des traductions. Ces traductions sont stockées dans une table différente avec une relation un-à-plusieurs. Par exemple newsarticles et newsarticle_translations. La quantité de languages disponible est déterminée dynamiquement par le même CMS.

Lors de la saisie d'un nouvel article de presse, l'éditeur doit entrer au moins une traduction, dont l'une des langues disponibles est celle qui lui appartient. Dans l'aperçu des articles de notre CMS, nous aimerions montrer une colonne avec le titre de l'article (traduit), mais comme aucune des langues n'est obligatoire (l'une d'entre elles est obligatoire mais je ne sais pas laquelle) i Je ne sais pas vraiment comment construire ma requête mysql pour sélectionner un titre pour chaque article, quelle que soit la langue saisie.

Et pour rendre le tout un peu plus difficile, notre responsable a demandé la possibilité de trier aussi le titre, donc l'extraction des traductions dans une requête séparée est exclue pour autant que je sache.

Quelqu'un a une idée sur la façon de résoudre le problème de la manière la plus efficace?

Voici l'il de mon schéma de la table, il pourrait aider

> desc news; 
+-----------------+----------------+------+-----+-------------------+----------------+ 
| Field   | Type   | Null | Key | Default   | Extra   | 
+-----------------+----------------+------+-----+-------------------+----------------+ 
| id    | int(10)  | NO | PRI | NULL    | auto_increment | 
| category_id  | int(1)   | YES |  | NULL    |    | 
| created   | timestamp  | NO |  | CURRENT_TIMESTAMP |    | 
| user_id   | int(10)  | YES |  | NULL    |    | 
+-----------------+----------------+------+-----+-------------------+----------------+ 


> desc news_translations; 
+-----------------+------------------+------+-----+---------+----------------+ 
| Field   | Type    | Null | Key | Default | Extra   | 
+-----------------+------------------+------+-----+---------+----------------+ 
| id    | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| enabled   | tinyint(1)  | NO |  | 0  |    | 
| news_id   | int(1) unsigned | NO |  | NULL |    | 
| title   | varchar(255)  | NO |  |   |    | 
| summary   | text    | YES |  | NULL |    | 
| body   | text    | NO |  | NULL |    | 
| language  | varchar(2)  | NO |  | NULL |    | 
+-----------------+------------------+------+-----+---------+----------------+ 

PS: J'ai bien sur les sous-requêtes et Coalesce solutions() mais semblent les trucs plutôt sales, se demandant si quelque chose de mieux savoir que je suis ne pense pas?

+1

Serait-il logique d'avoir aussi un champ 'title' dans le tableau' news' qui serait utilisé comme titre par défaut un article de nouvelles? Même si c'est seulement pour l'utilisation backend? –

+0

Ce serait, mais ce genre de redondance serait mon dernier recours. Je suis à la recherche d'une solution plus propre/meilleure, mais merci pour la suggestion. – ChrisR

+0

Peut-être un LEFT JOIN? – Benubird

Répondre

1

Ce n'est pas une approche rapide, mais je pense que cela vous donne ce que vous voulez.
Laissez-moi savoir comment cela fonctionne, et nous pouvons travailler sur la vitesse suivante :)

select nt.title 
    from news n 
    join news_translations nt on(n.id = nt.news_id) 
where nt.title is not null 
    and nt.language = (
      select max(x.language) 
      from news_translations x 
      where x.title is not null 
      and x.new_id = nt.news_id) 
order 
    by nt.title; 
+0

merci, ce n'est pas ce dont j'avais besoin, mais il a mis mon sur mon chemin pour trouver la solution parfaite! – ChrisR

1

En supposant que j'ai bien lu votre problème, vous voulez obtenir une liste de titres pour les articles, en préférant la langue "requise"? Une requête pour cela pourrait aller le long des lignes de ...

SELECT * FROM (
    SELECT nt.`title`, nt.news_id 
    FROM news n 
     INNER JOIN news_translations nt ON (n.id = nt.news_id) 
    WHERE title != '' 
    ORDER BY 
     CASE 
      WHEN nt.language = 'en' THEN 3 
      WHEN nt.language = 'jp' THEN 2 
      WHEN nt.language = 'de' THEN 1 
      ELSE 0 END DESC 
) AS t1 
GROUP BY `news_id` 

Cet exemple préfère un titre en anglais (en) le cas échéant, japonais (jp) comme deuxième préférence, et l'allemand (de) comme troisième , mais affichera la première entrée 'other' si aucune des langues demandées n'est disponible.

+0

Presque, la commande n'est pas le problème, c'est la sélection du bon enregistrement de la table news_translations qui a un titre entré. J'ai essayé votre requête et il y a encore des scénarios lorsqu'un titre vide est retourné bien que l'un des titres soit entré dans les enregistrements de traduction associés. – ChrisR

+2

Oh, je vois ... Je n'avais pas réalisé qu'il y aurait des entrées vides là-dedans. Vous pourriez potentiellement résoudre cela en ajoutant un "WHERE title! = ''/IS NOT NULL" à la sélection interne. Faites-moi savoir comment vous allez, ou si j'ai raté le point à nouveau :) –