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

 MySQL Discussion :

Sélections aléatoires consécutives dans une table (sans répétition)


Sujet :

MySQL

  1. #1
    Candidat au Club
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mai 2021
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Sélections aléatoires consécutives dans une table (sans répétition)
    Bonjour,

    Problème PHP/MySQL

    J'ai une table qui contient X enregistrements.
    Chaque jour, j'effectue un tirage au sort parmi ces X enregistrements.
    Quel est le moyen le plus simple pour ne pas avoir le même tirage aléatoire deux jours consécutifs ?

    Cela fait plusieurs jours que je sèche sur ce problème !
    J'ai testé pas mal de choses... en vain !
    Je suis nouveau sur ce forum. J'ai fait des recherches pour voir si ce genre de problème avait déjà été traité mais je n'ai rien trouvé !
    Merci pour votre aide !

  2. #2
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 909
    Points
    38 909
    Billets dans le blog
    9
    Par défaut
    Bonjour

    Une possibilité, si X n'est pas trop important : affecter un numéro à chaque ligne avec la fonction row_number() et utiliser la fonction rand() calibrée pour correspondre à l'effectif de la table afin de rechercher la ligne dont le numéro correspond à ce rand().

    Si le contenu de la table varie peu et qu'il est volumineux, vous pouvez n'affecter le numéro de ligne qu'une fois par semaine par exemple pour gagner du temps .

    Edit : il ne faut pas utiliser le rsultat du rand() avec la valeur d'une colonne de type auto_increment, car il y a un risque que la valeur de rand() tombe sur un "trou" de numérotation (valeur d'incrément non commitée ou supprimée). D'où la nécessité d'utiliser row_number. Attention toutefois : les fonctions OLAP ne sont prises en compte par MySQL que depuis la V8.

  3. #3
    Candidat au Club
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2021
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Mai 2021
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Fonction RAND sans répétition
    Citation Envoyé par escartefigue Voir le message
    Bonjour

    affecter un numéro à chaque ligne avec la fonction row_number() et utiliser la fonction rand() calibrée pour correspondre à l'effectif de la table afin de rechercher la ligne dont le numéro correspond à ce rand().

    Attention toutefois : les fonctions OLAP ne sont prises en compte par MySQL que depuis la V8.
    Bonjour et merci pour votre réponse.
    Il n'y a même pas besoin d'affecter un numéro à chaque ligne puisqu'il y a l'ID ?
    Je ne connaissais pas la fonction row_number(). Je viens de regarder et je ne comprends l'utilité qu'elle pourrait avoir dans le problème que j'ai à résoudre.
    Quand à la fonction OLAP, je suis plutôt au niveau débutant en MySQL et PHP et en suis, pour le moment aux fonctions de base !
    Merci à vous pour vous être penché sur mon problème et bonne journée.

  4. #4
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 909
    Points
    38 909
    Billets dans le blog
    9
    Par défaut
    Comme je l'expliquai plus haut, si la colonne ID est de type auto_increment, alors il peut y avoir des valeurs manquantes : lignes insérées non commitées d'une part et lignes supprimées par DELETE d'autre part.
    du coup, utiliser un rand() peut, par malchance, produire une valeur d'ID qui n'existe pas : la solution est alors inapplicable.
    C'est pourquoi je propose de calculer un rang avc des valeurs contiguës pour ce besoin.
    A cet effet, la fonction row_nomber() est parfaite

    Il faut également penser à veiller à ce que :
    • si rand() renvoie zéro, alors il faut remplacer la valeur obtenue par une autre, par exemple 1
    • si rand() renvoie une valeur supérieure à l'effectif de la table (obtenu par count(*), il faut également remplacer la valeur obtenue par une autre.

  5. #5
    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
    6 381
    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 : 6 381
    Points : 19 065
    Points
    19 065
    Par défaut
    Salut Philippe51430.

    Citation Envoyé par Philippe51430
    Quel est le moyen le plus simple pour ne pas avoir le même tirage aléatoire deux jours consécutifs ?
    Il faut gérer deux cas, qui sont :

    a) comment effectuer le tirage au sort ?
    Pour cela, il vous faut une colonne numéroté, allant de 1 à N, sans trous.
    D'où la remarque de Escartefigue, de ne pas utiliser la colonne "id" servant de clef primaire, puisque cellee-ci peut admettre des trous.

    La fonction rand() permet de sélectionner au hasard, un numéro compris entre 1 et N.

    b) ne pas choisir deux fois de suite le même tirage.
    Il vous faut stocker quelque part, le tirage de la veille.
    Et dans le tirage du jour, exclure le résultat de la veille. Comment ?
    En recommençant le tirage s'il vous donne le résultat de la veille.

    La fonction rand() vous retourne un résultat compris entre 0 et 1 (comme une probabilité).
    Voici un exemple basique de tirage au sort de deux lignes.
    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
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE IF NOT EXISTS `base`
            DEFAULT CHARACTER SET `latin1`
            DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `test`
    --------------
     
    --------------
    CREATE TABLE `test`
    ( `id`   integer unsigned  NOT NULL auto_increment primary key,
      `val`  varchar(255)      NOT NULL
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `test` (`id`,`val`) VALUES
      (01,'un'),        (05,'deux'),       (08,'trois'),
      (12,'quatre'),    (15,'cinq'),       (17,'six'),
      (22,'sept'),      (28,'huit'),       (30,'neuf'),
      (31,'dix'),       (35,'onze'),       (37,'douze'),
      (38,'treize'),    (40,'quatorze')   ,(42,'quinze'),
      (45,'seize'),     (47,'dix-sept')   ,(48,'dix-huit'),
      (51,'dix-neuf'),  (55,'vingt'),      (57,'vingt-et-un'),
      (61,'vingt-deux'),(63,'vingt-trois'),(68,'vingt-quatre'),
      (71,'vingt-cinq'),(72,'vingt-six'),  (75,'vingt-sept'),
      (78,'vingt-huit'),(81,'vingt-neuf'), (83,'trente')
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +----+--------------+
    | id | val          |
    +----+--------------+
    |  1 | un           |
    |  5 | deux         |
    |  8 | trois        |
    | 12 | quatre       |
    | 15 | cinq         |
    | 17 | six          |
    | 22 | sept         |
    | 28 | huit         |
    | 30 | neuf         |
    | 31 | dix          |
    | 35 | onze         |
    | 37 | douze        |
    | 38 | treize       |
    | 40 | quatorze     |
    | 42 | quinze       |
    | 45 | seize        |
    | 47 | dix-sept     |
    | 48 | dix-huit     |
    | 51 | dix-neuf     |
    | 55 | vingt        |
    | 57 | vingt-et-un  |
    | 61 | vingt-deux   |
    | 63 | vingt-trois  |
    | 68 | vingt-quatre |
    | 71 | vingt-cinq   |
    | 72 | vingt-six    |
    | 75 | vingt-sept   |
    | 78 | vingt-huit   |
    | 81 | vingt-neuf   |
    | 83 | trente       |
    +----+--------------+
    --------------
    SELECT      *
        FROM  (    SELECT    *,
                             row_number() over(order by `id`) as rang
                     FROM    `test`) as x
    ORDER BY  rand()
    LIMIT 2
    --------------
     
    +----+------------+------+
    | id | val        | rang |
    +----+------------+------+
    | 81 | vingt-neuf |   29 |
    | 37 | douze      |   12 |
    +----+------------+------+
    --------------
    COMMIT
    --------------
     
    Appuyez sur une touche pour continuer...
    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

Discussions similaires

  1. [DATA] Vérifier si une valeur est dans une table sans PROC SQL
    Par Filippo dans le forum SAS Base
    Réponses: 5
    Dernier message: 02/12/2009, 11h05
  2. Ajout dans une table sans doublon
    Par Cbonniot dans le forum Langage SQL
    Réponses: 5
    Dernier message: 18/05/2009, 10h31
  3. Réponses: 1
    Dernier message: 30/04/2009, 10h16
  4. [DOM] Script de sélection de row dans une table
    Par Alain G dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 22/08/2007, 21h58
  5. Réponses: 3
    Dernier message: 21/05/2007, 15h31

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