2017-06-09 3 views
0

Je cours un cronjob tous les jours pour un site de notation qui exécute un script qui choisissent 3 images aléatoires de chaque catégorie les visiteurs peuvent ensuite évaluer les images les unes contre les autres comme "Image 1 versus image 2 -> lequel préférez-vous? ", cela fonctionne très bien.Comment puis-je m'assurer que deux lignes avec le même numéro dans la base de données ne sont pas choisies?

Le problème est permet de dire qu'il ya deux du même type d'images

Supposons

  • id 1 est une ford mustang gt vue avant
  • id 2 est une ford mustang gt vue de face juste légèrement différente que l'ID 1

Ceci est un problème parce que si les deux id 1 et id 2 est choisi, c'est comme dire deux images assez identiques sont contre chaque autre? Donc, j'ai créé une « colonne de séparation » où je donne les images qui représentent le même le même nombre dans ce cas simplifié id 1 et id 2 ont tous deux numéro de séparateur 1 :)

structure de base de données

Tableau Voitures

cars_id | cars_category | cars_source | separator 
--------+---------------+---------------+----------- 
1  | 1   | 123.jpg  | 1 
2  | 1   | 242.jpg  | 1 
3  | 2   | 532.jpg  | 2 
4  | 2   | 531.jpg  | 3 
5  | 2   | 45fd.jpg  | 3 
6  | 3   | da3.jpg  | 4 

script PHP actuel qui choisir 3 images au hasard dans chaque catégorie

$cat1 = 1; 
$cat2 = 2; 
$cat3 = 3; 
$stmt = $dbCon->prepare(" INSERT INTO daily_versus (daily_versus_source, daily_versus_category) " 
     . " (SELECT cars_source, cars_category " 
     . " FROM cars " 
     . " WHERE cars_category IN (?) ORDER BY RAND() LIMIT 3) " 
     . " UNION " 
     . " (SELECT cars_source, cars_category " 
     . " FROM cars " 
     . " WHERE cars_category IN (?) ORDER BY RAND() LIMIT 3) " 
     . " UNION " 
     . " (SELECT cars_source, cars_category " 
     . " FROM cars " 
     . " WHERE cars_category IN (?) ORDER BY RAND() LIMIT 3) "); 
$stmt->bind_param('iii', $cat1, $cat2, $cat3); 
if ($stmt->execute()) { 
    echo "Success VERSUS/INSERT"; 
} else { 
    echo "Fail VERSUS/INSERT"; 
} 

les œuvres ci-dessus comme un charme, mais ce serait le plus intelligent approac h pour intégrer les numéros de séparateur de sorte que deux voitures identiques ne peuvent pas être choisies ... Donc, fondamentalement, si une voiture avec le numéro de séparateur "x" a été choisi le script ne peut pas choisir une autre voiture avec ce même numéro de séparateur?

Répondre

-1

Classement par [seperator] et sélectionnez le premier.

+0

Cela n'a pas rapport à ce que j'ai demandé – Javaish

0

Le plus simple serait de grouper chaque requête par séparateur. Mysql prendra une valeur "aléatoire" de chaque groupe.

... 
(SELECT cars_source, cars_category 
FROM cars 
WHERE cars_category IN (?) 
GROUP BY SEPARATOR 
ORDER BY RAND() LIMIT 3) 
... 

Cependant, ce n'est pas vraiment aléatoire, pour chaque groupe de séparateurs, il ne prendra probablement qu'une (et toujours la même) valeur chaque fois que ce séparateur est choisi.

Mieux (- pour commencer un commentaire/Dénudez avant d'utiliser)

... 
(SELECT cars_source, cars_category 
FROM 
(select 
    (select id  -- one random id, for each of the 3 random separators 
    from cars 
    where separator = ocars.separator -- will be a diff separator for each row in the outer query 
    order by rand() limit 1 
    ) as rand_id 
    from cars as ocars 
    WHERE cars_category IN (?) 
    group by separator -- each separator only once 
    order by rand()  -- random separators 
    limit 3    -- 3 random separators 
) as cars_id 
left join cars on cars.id = cars_id.rand_id -- join the full row for each rand_id 
) 
... 

vous devriez avoir des index, sur id, et le séparateur, peut-être la catégorie

+0

Vous l'avez surtout dit dans votre réponse, mais pour être super clair pour les gens de la tl; dr: la première liste de code NE FONCTIONNERA PAS. MySql effectue le 'group by' avant le' order by rand', donc généralement (mais pas garanti) renvoie le même élément pour chacun des séparateurs distincts, puis mélange * ceux *. Je suis curieux de savoir pourquoi vous et OP ont tous deux favorisé 'cars_category IN (?)' Sur 'cars_category = (?)' Mais ... –

+0

le premier "group by" fonctionnera dans des cas spéciaux. par exemple. si l'ordre physique dans la table a changé. Mais oui la "commande par" n'affecte que le "séparateur", et non l'élément dans un groupe du même "séparateur". À propos du "in()", je viens de le copier. – Martin

+0

Cela semble un peu déroutant à première vue, je vais essayer de l'analyser à travers et voir si c'est ce que je cherche :) – Javaish