Partage
  • Partager sur Facebook
  • Partager sur Twitter

[SQL] Sélectionner 5 lignes pour 4 critères en une requête

    9 novembre 2010 à 13:07:23

    Bonjour,

    Dans le cadre d'un mini-jeu de culture historique, j'ai une base de questions dans laquelle sont sélectionnées 20 questions au hasard posées au joueur.
    Dans une colonne de la table, les questions sont classées en fonction de 4 critères ("Antiquité", Moyen Âge", "Temps modernes" et "Monde contemporain" puisque c'est un jeu historique, respectivement désignés dans la base par les chiffres 1, 2, 3, 4) : dans le tableau ci-dessous "question_categorie".
    J'expose mon problème : j'aimerais que 5 questions de chacune de ces catégories soient sélectionnées soit 20 questions au total (5 x 4).

    Un petit schéma très simplifié de la table en question :

    question_id ... question_categorie
    1 ... 4
    2 ... 3
    3 ... 1
    4 ... 3
    5 ... 1
    6 ... 2
    7 ... 4
    8 ... 3
    ... ... ...


    J'aimerais faire ça en une requête SQL (et non 4). Je me demande si c'est possible ?
    J'espère avoir été clair. :euh:

    Merci par avance pour vos réponses. :)
    • Partager sur Facebook
    • Partager sur Twitter
    Philisto.fr : site d'Histoire pour lycéens, étudiants, ... - Paul de Cassagnac (livre)
    Anonyme
      9 novembre 2010 à 13:13:46

      Fournis-nous la structure de la table (CREATE TABLE..) plus des données (INSERT INTO..) pour tester.
      Tu veux 5 lignes prises au pifomètre ou pas ?
      • Partager sur Facebook
      • Partager sur Twitter
        9 novembre 2010 à 13:18:37

        Voici la structure de la table :

        CREATE TABLE IF NOT EXISTS `concours_questions` (
          `question_id` int(11) NOT NULL auto_increment,
          `question_intitule` varchar(500) character set latin1 collate latin1_general_ci NOT NULL,
          `question_reponse1` varchar(200) character set latin1 collate latin1_general_ci NOT NULL,
          `question_reponse2` varchar(200) character set latin1 collate latin1_general_ci NOT NULL,
          `question_reponse3` varchar(200) character set latin1 collate latin1_general_ci NOT NULL,
          `question_reponse4` varchar(200) character set latin1 collate latin1_general_ci NOT NULL,
          `question_reponse` enum('1','2','3','4') character set latin1 collate latin1_general_ci NOT NULL,
          `question_explication` text character set latin1 collate latin1_general_ci NOT NULL,
          `question_categorie` enum('1','2','3','4') character set latin1 collate latin1_general_ci NOT NULL,
          `question_entrainement` enum('0','1') character set latin1 collate latin1_general_ci NOT NULL default '0',
          `question_timestamp` int(11) NOT NULL,
          PRIMARY KEY  (`question_id`)
        ) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=72 ;
        


        Oui, il s'agit bien de choisir 5 questions au hasard à chaque fois.
        Actuellement je ne peux en choisir que 20 au hasard sans en prendre en compte le critère "question_categorie".

        Edit : j'oubliais quelques données :
        INSERT INTO `concours_questions` (`question_id`, `question_intitule`, `question_reponse1`, `question_reponse2`, `question_reponse3`, `question_reponse4`, `question_reponse`, `question_explication`, `question_categorie`, `question_entrainement`, `question_timestamp`) VALUES
        (1, 'De quelle couleur étaient les habits des moines de l\\''abbaye de Cluny ?', 'Noir', 'Pourpre', 'Marron', 'Blanc', '1', 'Les moines de l\\''abbaye de Cluny (fondée en 909-910) avaient la particularité d\\''être habillés de noir.', '2', '1', 1284232373),
        (2, 'Quel empereur romain succéda à Tibère ?', 'Caligula', 'Néron', 'Claude', 'Auguste', '1', 'Les empereurs romains successifs de la première moitié du Ier siècle étaient respectivement Auguste, Tibère, Caligula, Claude et Néron.', '1', '1', 1284232553),
        (3, 'Qui est le père de Charlemagne ?', 'Louis le Pieux', 'Pépin le Bref', 'Charles Martel', 'Charles le Chauve', '2', 'Charles Martel est le grand-père de Charlemagne, Pépin son père, Louis le Pieux son fils et Charles le Chauve son petit-fils.', '2', '1', 1284232734),
        (4, 'Quelle ville n\\''est jamais passée sous le joug ottoman ?', 'Constantinople', 'Vienne', 'Belgrade', 'Athènes', '2', 'Les Turcs ont mis deux fois le siège devant Vienne (en 1529 et 1683) mais n\\''ont jamais réussi à prendre la ville.', '3', '1', 1285679511),
        (5, 'Au cours de quel siècle l\\''Espagne musulmane éclata en de multiples principautés (taifas) ?', 'Le VIIIe siècle', 'Le IXe siècle', 'Le Xe siècle', 'Le XIe siècle', '4', 'Le XIe siècle, période d\\''instabilité politique dans Al-Andalous, vit l\\''éclatement du pouvoir central en de multiples principautés, plus ou moins puissantes.', '2', '1', 1285680883),
        (6, 'Quel personnage n\\''était pas présent à la conférence de Yalta (1945) ?', 'Joseph Staline', 'Charles de Gaulle', 'Franklin D. Roosevelt', 'Winston Churchill', '2', 'Le but de la conférence de Yalta, réunissant les trois grands (futurs) vainqueurs de l\\''Allemagne nazie, était de hâter la fin de la guerre et régler le sort de l\\''Europe après l\\''effondrement du IIIe Reich.', '4', '1', 1285681217),
        (7, 'Qu\\''était Louis XV par rapport à Louis XIV ?', 'Son arrière-petit-fils', 'Son petit-fils', 'Son fils', 'Son frère', '1', 'Louis XV, né en 1710, n\\''avait que 5 ans à la mort de son arrière-grand-père Louis XIV (1715). Son grand oncle le duc d\\''Orléans fut proclamé Régent du Royaume.', '3', '1', 1285681781),
        (8, 'Quel président américain succèda à Jimmy Carter ?', 'Gerald Ford', 'Richard Nixon', 'Ronald Reagan', 'Bill Clinton', '3', 'Ronald Regan fut élu en 1980 et réélu en 1984. Durant la campagne de 1980, il aura la plaisanterie suivante : \\"La dépression c\\''est quand vous perdez votre travail, la récession c\\''est quand votre voisin perd son travail, et la reprise c\\''est quand Jimmy Carter perd son travail\\".', '4', '1', 1285690060),
        (9, 'Qui fut le dernier souverain de l\\''empire achéménide ?', 'Cyrus II', 'Xerxès II', 'Artaxerxès III', 'Darius III', '4', 'Darius III, roi de 336 à 330 av. J.-C. eut à subir l\\''invasion d\\''Alexandre le Grand. Sa mort par assassinat en 330 marqua la fin de l\\''empire achéménide.', '1', '1', 1285848856),
        (10, 'Qui fut le premier président de la IIIe République ?', 'Jules Grévy', 'Adolphe Thiers', 'Patrice de Mac-Mahon', 'Sadi Carnot', '2', 'Adoplhe Thiers fut président de 1871 à 1873, Mac-Mahon de 1873 à 1879, Grévy de 1879 à 1887 et Carnot de 1887 à 1894.', '4', '1', 1285849308),
        (11, 'Sous quel règne débuta la croisade des Albigeois ?', 'Louis VII', 'Philippe II Auguste', 'Louis VIII', 'Saint Louis', '2', 'A partir de 1207-1208, le pape Innocent III fait prêcher la croisade contre les Albigeois. Philippe Auguste est alors roi de France (de 1180 à 1223).', '2', '0', 1285855003),
        (12, 'Quelle est la divinité des chevaux dans le panthéon gaulois ?', 'Epona', 'Artio', 'Abellio', 'Belenus', '1', 'Artio est la divinité des ours, Abellio des pommiers et Belenus du Soleil.', '1', '0', 1285872228),
        (13, 'Dans quelle ville a été signé le traité mettant fin à la guerre d\\''Indépendance américaine ?', 'Yorktown', 'Boston', 'Versailles', 'Londres', '3', 'Le traité de Versailles mettant fin à la guerre d\\''Indépendance est signé par la France, la Grande-Bretagne, l\\''Espagne en 1783.', '3', '0', 1285872793),
        (14, 'Quelle unité de mesure de température tient son nom d\\''un lord anglais ?', 'Le degré celsius', 'Le degré fahrenheit', 'Le kelvin', 'Le degré rankine', '3', 'Le physicien britannique William Thompson, mieux connu sous le nom de Lord Kelvin (1824-1907), est à l\\''origine de l\\''introduction d\\''un zéro absolu correspondant à l\\''absence absolue d\\''agitation thermique et de pression d\\''un gaz.', '4', '0', 1286038290),
        (15, 'Quel était le surnom de Louis X de France ?', 'Le Lion', 'Le Bel', 'Le Hutin', 'Le Pieux', '3', '\\"Le Hutin\\" signifie \\"le querelleur\\".', '2', '0', 1286049107),
        (16, 'Combien de colonies comportaient les Etats-Unis à leur indépendance ?', '7', '10', '13', '20', '3', 'Ces 13 colonies sont la Virginie, le Massachusetts, le New Hampshire, le Maryland, le Connecticut, Rhode Island, le Delaware, la Caroline du Nord, la Caroline du Sud, le New Jersey, New York, la Pennsylvanie et la Géorgie.', '3', '0', 1286108236),
        (17, 'Quel oeuvre n\\''a pas été écrite par Aristophane ?', 'Les Nuées', 'Gorgias', 'Les Grenouilles', 'Ploutos', '2', 'Aristophane, poète comique grec du Ve siècle av. J.-C. a écrit (entres autres) \\"Les Nuées\\", \\"Les Grenouilles\\" et \\"Ploutos\\". \\"Gorgias\\" est une oeuvre de Plkaton.', '1', '0', 1286375915),
        (18, 'Quel événement provoqua la mort de Périclès en 429 av. J.-C. ?', 'Une épidémie de peste', 'Un complot politique', 'Une bataille contre les Spartiates', 'Une condamnation à mort pour trahison', '1', 'La peste à Athènes en 430-429 entraîna la mort de Périclès, au début de la guerre du Péloponnèse (431-404). Ce fut une catastrophe morale pour les Athéniens qui perdirent leur chef charismatique.', '1', '0', 1286376273),
        (19, 'A quel courant littéraire appartient Victor Hugo ?', 'Au romantisme', 'Au réalisme', 'Au symbolisme', 'Au Parnasse', '1', 'Victor Hugo (1802-1885) est l\\''un des plus importants auteurs romantiques du XIXe siècle, et d\\''ailleurs l\\''un des derniers grands romantiques !', '4', '0', 1286376760),
        (20, 'Quel empereur romain est originaire d\\''Hispanie ?', 'Caligula', 'Vespasien', 'Nerva', 'Trajan', '4', 'Trajan est né en 53 à Italica dans l\\''actuelle Espagne. Il est le premier empereur non originaire d\\''Italie.', '1', '0', 1286377218),
        (21, 'Dans quelle ville se sont tenus les Jeux olympiques de 1896 ?', 'Paris', 'Athènes', 'Londres', 'Rome', '2', 'L\\''année 1896 est celle de la rénovation des Jeux olympiques grâce à l\\''action de Pierre de Coubertin. Ces premiers jeux se tiennent à Athènes.', '4', '0', 1286378674),
        (22, 'Durant la Seconde Guerre mondiale, comment se nommait l\\''opération lancée par les Britanniques visant à repousser les Allemands d\\''Egypte ?', 'L\\''opération Torch', 'L\\''opération Lightfoot', 'L\\''opération Ironclad', 'L\\''opération Crusader', '2', 'Suite à la victoire défensive anglaise d\\''Alam el Halfa (août 1942) face à l\\''Afrikacorps de Rommel, Montgomery lance dans l\\''automne 1942 l\\''opération Lightfoot visant à chasser l\\''armée allemande d\\''Egypte. C\\''est un succès pour les Alliés (seconde victoire d\\''El Alamein).', '4', '0', 1286379391),
        (23, 'A qui Napoléon s\\''opposa-t-il lors de la bataille d\\''Iéna ?', 'Aux Prussiens', 'Aux Russes', 'Aux Anglais', 'Aux Autrichiens', '1', 'Lors de la bataille d\\''Iéna le 14 octobre 1806, Napoléon écrasa l\\''armée prussienne. Il entra dans Berlin le 27 octobre et les Prussiens signèrent l\\''armistice le 30 novembre.', '3', '0', 1286386268),
        (24, 'De quel pays Philippe V, petit-fils de Louis XIV, a-t-il été roi ?', 'La Prusse', 'Les Provinces-Unies', 'L\\''Espagne', 'Le Portugal', '3', 'Philippe V, roi d\\''Espagne de 1700 à 1746, est le premier représentant de la dynastie des Bourbons à la mort de Charles II d\\''Espagne. Son règne est le plus long de la monarchie espagnole.', '3', '0', 1286450038),
        (25, 'Quelle ville fut l\\''objet d\\''un violent séisme le 1er novembre 1755 ?', 'Lisbonne', 'Bordeaux', 'Barcelone', 'Madrid', '1', 'Ce tremblement de terre fut l\\''un des plus meurtriers de l\\''histoire, avec 50 000 à 100 000 victimes selon les sources. Il suscita des débats autour de la Providence ou de la théodicée chez les philosophes des Lumières.', '3', '0', 1286450380);
        
        • Partager sur Facebook
        • Partager sur Twitter
        Philisto.fr : site d'Histoire pour lycéens, étudiants, ... - Paul de Cassagnac (livre)
          9 novembre 2010 à 13:24:07

          Tu ne peux pas, il faut faire 4 requêtes.
          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            9 novembre 2010 à 13:37:36

            Il est possible en une requête, d'afficher les 5 dernières (par timestamp) questions pour chaque catégories.
            Mais le caractère aléatoire c'est pas possible.
            • Partager sur Facebook
            • Partager sur Twitter
              9 novembre 2010 à 13:38:55

              Ah mince, dommage.
              Je vais donc faire 4 requêtes.

              Merci pour vos réponses.

              Edit : je marque que vos réponses m'ont aidé mais je ne mets pas le sujet en résolu au cas où quelqu'un ait une solution.
              • Partager sur Facebook
              • Partager sur Twitter
              Philisto.fr : site d'Histoire pour lycéens, étudiants, ... - Paul de Cassagnac (livre)
              Anonyme
                9 novembre 2010 à 13:57:53

                Au cas ou:

                Afficher les 5 dernières questions pour chaque catégorie :
                SELECT question_categorie, question_id, question_timestamp
                FROM concours_questions AS a
                WHERE (	SELECT Count(*)
                	FROM concours_questions AS b
                	WHERE a.question_categorie=b.question_categorie
                	  AND b.question_timestamp < a.question_timestamp ) < 5
                ORDER BY question_categorie, question_timestamp DESC
                
                • Partager sur Facebook
                • Partager sur Twitter
                  9 novembre 2010 à 14:48:20

                  J'ai peur de dire une énorme connerie, vu que vous avez l'air sûrs de vous, mais il me semble qu'avec quelques imbrications de requêtes, on peut faire ce qu'il veut en un coup :

                  SELECT *
                  FROM (
                  	(SELECT * FROM concours_question WHERE question_categorie = '1' ORDER BY RAND() LIMIT 5) as cat_1
                  	UNION
                  	(SELECT * FROM concours_question WHERE question_categorie = '2' ORDER BY RAND() LIMIT 5) as cat_2
                  	UNION
                  	(SELECT * FROM concours_question WHERE question_categorie = '3' ORDER BY RAND() LIMIT 5) as cat_3
                  	UNION
                  	(SELECT * FROM concours_question WHERE question_categorie = '4' ORDER BY RAND() LIMIT 5) as cat_4
                  ) as all_cat
                  ORDER BY RAND()
                  


                  Non ??
                  • Partager sur Facebook
                  • Partager sur Twitter
                    9 novembre 2010 à 14:56:23

                    Oui Taguan sa peut marcher mais le hasard avec les requêtes c'est impossible , ce que je te propose tu utilises une variable qui change et qui se fait au hasard en fonction de ta requête (sa dépend de ton langage)
                    • Partager sur Facebook
                    • Partager sur Twitter
                      9 novembre 2010 à 15:15:53

                      Ah... Mais ça fait quoi RAND() si c'est pas générer un nombre aléatoire (ou pseudo-aléatoire quoi, je pense pas que ça change quelque chose pour le projet ici).

                      Je sais que c'est pas top à utiliser car ça prend du temps comme truc, mais s'il n'a pas 100.000 questions dans sa table, ça me parait tout à fait utilisable...
                      • Partager sur Facebook
                      • Partager sur Twitter
                        9 novembre 2010 à 15:34:16

                        Faut juste qu'il oubli pas d'utiliser RAND(1,n) car sinon ça va lui faire bizarre.
                        • Partager sur Facebook
                        • Partager sur Twitter

                        [SQL] Sélectionner 5 lignes pour 4 critères en une requête

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown