JeuWeb - Crée ton jeu par navigateur
Le 'contraire' d'une jointure - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Le 'contraire' d'une jointure (/showthread.php?tid=872)



Le 'contraire' d'une jointure - Yoda54 - 01-03-2007

Bonjour,

Je suis entrain de bloquer sur une requête SQL. J'ai une première table 'joueurs' avec le champ 'id_joueur' et une seconde appelée 'marche' avec le même champ id_joueur. Mon but est de compter le nombre de joueur présents dans la première table qui n'apparaissent pas dans la seconde.
La méthode la plus évidente consiste à compter le nombre de joueur dans la première table (1ère requête) puis de compter le nombre de joueurs dans la seconde (2ême requête) et enfin de faire la soustraction.
Mais n'existe pas une possibilité de faire ceci en une seule requête?
Merci d'avance.


RE: Le 'contraire' d'une jointure - Dradge - 01-03-2007

Pour ce la tu peux utiliser le mot clé NOT IN ce qui te donne :

Code :
SELECT COUNT(*) AS nombre FROM table1 WHERE id NOT IN(SELECT id FROM table2)

En français la requete te donne : "Compter les lignes de la table1 pour lesquels le champ id[/code] n'est pas présent dans la table table2"

Note : Le NOT IN requiert que les champs avant le NOT IN soient dans le même ordre et en même nombre que les champs renvoyés par la requête imbriquée.

Voilà j'espère avoir été assez clair.


RE: Le 'contraire' d'une jointure - pascal - 01-03-2007

je verrais bien une requete dans le genre :
Code :
SELECT COUNT(joueur.id_joueur) FROM joueur LEFT JOIN marche
USING(id_joueur) WHERE marche.id_joueur IS NULL

A+

Pascal


RE: Le 'contraire' d'une jointure - Roworll - 01-03-2007

Petite note au passage, si c'est pour faire une différence globale (ie sur toutes les lignes sans distinction) l'utilisation de deux COUNT() successifs sera plus performante qu'une requête NOT IN ou un JOIN à moins que les tables liées soient très petites.

De plus, le NOT IN n'est pas supporté dans toutes les versions de MySQL.


RE: Le 'contraire' d'une jointure - Yoda54 - 01-03-2007

Merci de vos réponses, j'allais justement poser la question de la performance entre les deux solutions proposées...:heuuu:
Je vais faire quelques petits tests dans mon coin et je vous tiens au courant.


RE: Le 'contraire' d'une jointure - Yoda54 - 01-03-2007

Voilà, une faois les tests effectués, il s'avère que les deux premières solutions sont quasi-équivalentes (généralement, la seconde est plus rapide de 2 à 5 centièmes de seconde pour 10.000 occurences). En revanche, l'utilisation de deux requête est généralement deux fois plus lente.
Voici le code utilisé pour ce test:

Code PHP :
<?php 
include('sql.php');
$debut=microtime(true);
for(
$i=1; $i<=10000; $i++)
{
$retour=mysql_query("SELECT COUNT(id_joueur) AS nbre FROM joueurs_carac WHERE id_joueur NOT IN(SELECT id_joueur FROM marche WHERE id_equipe=1) AND id_equipe=1") or die(mysql_error());
$data=mysql_fetch_assoc($retour);
}
$fin=microtime(true);
$solution1=$fin-$debut;
echo
'solution1='.$solution1.'<br />';
$debut=microtime(true);
for(
$i=1; $i<=10000; $i++)
{
$retour=mysql_query("SELECT COUNT(id_joueur) AS nbre FROM joueurs_carac LEFT JOIN marche USING(id_joueur) WHERE marche.id_joueur IS NULL AND joueurs_carac.id_equipe=1") or die(mysql_error());
$data=mysql_fetch_assoc($retour);
}
$fin=microtime(true);
$solution2=$fin-$debut;
echo
'solution2='.$solution2.'<br />';
$debut=microtime(true);
for(
$i=1; $i<=10000; $i++)
{
$retour=mysql_query("SELECT COUNT(id_joueur) AS nbre FROM joueurs_carac WHERE id_equipe=1") or die(mysql_error());
$data=mysql_fetch_assoc($retour);
$retour=mysql_query("SELECT COUNT(id_joueur) As nbre FROM marche WHERE id_equipe=1") or die(mysql_error());
$data1=mysql_fetch_assoc($retour);
$nbre=$data['nbre']-$data1['nbre'];
}
$fin=microtime(true);
$solution3=$fin-$debut;
echo
'solution3='.$solution3;
mysql_close();

A noter que la table "joueurs_carac" comporte 10640 entrées dont 19 correspondent à la clause WHERE et la table "marche en comporte 2, les deux répondant à la clause WHERE.

Merci pour toutes vos précisions.
Amicalement,