IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Extraire premier résultat ORDER BY FIELD


Sujet :

Requêtes MySQL

  1. #1
    Membre éclairé

    Inscrit en
    décembre 2009
    Messages
    146
    Détails du profil
    Informations forums :
    Inscription : décembre 2009
    Messages : 146
    Points : 881
    Points
    881
    Par défaut Extraire premier résultat ORDER BY FIELD
    Bonjour,

    Je voudrais réaliser une extraction d'une information variable selon la langue de l'utilisateur, mais qui propose une autre langue par défaut, et la langue originale si rien n'est trouvé.
    Comme cette phrase n'est certainement pas très claire et que je ne vois pas comment la clarifier, j'ai mis un petite exemple sur SQL Fiddle

    Voici le contenu :
    J'ai une table book contenant des informations sur les livres (ici seul l'identifiant pour ne pas s'encombrer d'informations inutiles) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CREATE TABLE book (
      id integer);
    Et une table book_title contenant les titres des livres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE TABLE book_title (
      id integer,
      title varchar(10),
      locale varchar(2),
      book_fk integer
      );
    Le titre est dans la langue spécifié dans le champ "locale".

    Donc avec ces données :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    INSERT INTO book (id) VALUES (1), (2), (3), (4);
     
    INSERT INTO book_title (id, title, locale, book_fk) VALUES 
      (1, 'Titre 1', 'fr', 1), 
      (2, 'Title 1', 'en', 1),
      (3, 'Titre 2', 'fr', 2),
      (4, 'Titolo 3', 'it', 3),
      (5, 'Title 4', 'en', 4),
      (6, 'Titolo 4', 'it', 4);
    J'ai 4 livres dont deux ont un titre dans 2 langues.
    Je voudrais obtenir (par exemple) prioritairement les titres en français, puis en anglais, et si aucun des deux n'est trouvé, le premier qui vient. Donc pour cela j'utilise ORDER BY FIELD :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT b.id, bt.title
    FROM book AS b
    INNER JOIN book_title bt
    ON b.id = bt.book_fk
    ORDER BY FIELD(locale, 'fr', 'en') DESC;
    Mais, comme son nom l'indique, order fait le tri et je voudrais n'avoir qu'un résultat par livre.
    Je pourrais sans doute utiliser des sous requêtes, mais cette exemple est simplifié et ma requête utilise en réalité déjà des sous-requêtes, donc si je pouvais éviter, ce serait bien.

    Si quelqu'un a une idée ou une indication qui pourrait me mettre sur la voie, je serais grandement intéressé

    Merci

  2. #2
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    février 2011
    Messages
    5 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : février 2011
    Messages : 5 070
    Points : 15 264
    Points
    15 264
    Par défaut
    Salut Sylvaner.

    Citation Envoyé par Sylvaner
    Je voudrais obtenir (par exemple) prioritairement les titres en français, puis en anglais, et si aucun des deux n'est trouvé, le premier qui vient.
    Citation Envoyé par Sylvaner
    je voudrais n'avoir qu'un résultat par livre.
    Tu veux en premier le français si celui-ci existe, sinon l'anglais si celui-ci existe et enfin une autre langue et ce, pour un livre donné.
    D'accord, c'est faisable, mais il manque juste la question des priorités !
    Pour ce faire, tu dois créer une table des priorités à partir de la colonne 'locale', comme ci-après :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    fr : 1
    en : 2
    it : 3
    de : 3
    jp : 3
    Ici, j'ai mis 1 pour 'fr' et 2 pour 'en' comme sur ton exemple. Ensuite, j'ai toujours mis 3 pour les autres langues.
    De ce fait, on a attribué un poids qui va servie au tri.
    Il reste juste à utiliser une astuce, qui est de faire l'usage de 'limit 1' pour récupérer que le premier tuple.
    Voici l'exemple de ce que je propose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
            DEFAULT CHARACTER SET `latin1`
            DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `book_title`
    --------------
     
    --------------
    CREATE TABLE `book_title`
    (
      `id`        integer unsigned NOT NULL AUTO_INCREMENT,
      `title`     char(20)         NOT NULL,
      `locale`    char(02)         NOT NULL,
      `book_fk`   integer unsigned NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO book_title (`title`, `locale`, `book_fk`) VALUES
    ('Titre 1',  'fr', 1),
    ('Title 1',  'en', 1),
    ('Titre 2',  'fr', 2),
    ('Titolo 3', 'it', 3),
    ('Title 4',  'en', 4),
    ('Titolo 4', 'it', 4)
    --------------
     
    --------------
    select * from book_title
    --------------
     
    +----+----------+--------+---------+
    | id | title    | locale | book_fk |
    +----+----------+--------+---------+
    |  1 | Titre 1  | fr     |       1 |
    |  2 | Title 1  | en     |       1 |
    |  3 | Titre 2  | fr     |       2 |
    |  4 | Titolo 3 | it     |       3 |
    |  5 | Title 4  | en     |       4 |
    |  6 | Titolo 4 | it     |       4 |
    +----+----------+--------+---------+
    --------------
    DROP TABLE IF EXISTS `priority`
    --------------
     
    --------------
    CREATE TABLE `priority`
    (
      `locale`    char(02) NOT NULL,
      `sort`      tinyint  NOT NULL,
      PRIMARY KEY (`locale`)
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `priority` (`locale`, `sort`) VALUES
    ('fr', 1),
    ('en', 2),
    ('it', 3)
    --------------
     
    --------------
    select * from priority
    --------------
     
    +--------+------+
    | locale | sort |
    +--------+------+
    | en     |    2 |
    | fr     |    1 |
    | it     |    3 |
    +--------+------+
    --------------
    select book_fk, title
    from book_title as tb1
    where locale = (
        select tb2.locale
        from       book_title as tb2
        inner join priority   as tb3
        on    tb3.locale  = tb2.locale
            where tb2.book_fk = tb1.book_fk
            order by tb3.sort limit 1)
    order by book_fk
    --------------
     
    +---------+----------+
    | book_fk | title    |
    +---------+----------+
    |       1 | Titre 1  |
    |       2 | Titre 2  |
    |       3 | Titolo 3 |
    |       4 | Title 4  |
    +---------+----------+
    --------------
    COMMIT
    --------------
     
    --------------
    SET AUTOCOMMIT = 1
    --------------
     
     
    Appuyez sur une touche pour continuer...
    Comme je viens de poser une possible solution, il y a certainement d'autres membres qui vont enrichir ou proposer une autre solutions.
    Et comme à l'habitude, je propose un sous-requête corrélée. On peut faire l'équivalent mais avec une jointure.
    Tu me dis si cela te convient ou pas.

    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

  3. #3
    Membre éclairé

    Inscrit en
    décembre 2009
    Messages
    146
    Détails du profil
    Informations forums :
    Inscription : décembre 2009
    Messages : 146
    Points : 881
    Points
    881
    Par défaut
    Merci pour cette réponse, c'est en effet une possibilité, mais le problème est que je le "poids" des langues va changer en fonction de la langue par défaut (Cette précision manquait dans mon message )

    Sinon j'ai trouvé en attendant cette solution pour le moment mais on est dans le top des requêtes de requêtes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT * FROM (
    SELECT b.id, bt.title
    FROM book AS b
    INNER JOIN book_title bt
    ON b.id = bt.book_fk
    ORDER BY FIELD(locale, 'en', 'it') DESC
    ) as g
    GROUP BY g.id;
    En remplacant 'it' par la langue par défaut de l'utilisateur, ça fonctionne et c'est pas trop lourd dans ce cas, mais cette solution est un peu lourd pour mon utilisation

Discussions similaires

  1. Extraire le résultat d'une BDD entre deux dates
    Par Filipegomes dans le forum C#
    Réponses: 3
    Dernier message: 14/11/2007, 17h47
  2. Réponses: 2
    Dernier message: 18/10/2007, 15h32
  3. Extraire les résultats d'un tri automatique
    Par billou06 dans le forum Excel
    Réponses: 5
    Dernier message: 28/06/2007, 02h49
  4. Réponses: 5
    Dernier message: 08/03/2007, 12h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo