Requête un peu compliquée

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Requête un peu compliquée

par VaN » 15 févr. 2008, 21:21

Oui, je comprend mieux.

par zeus » 15 févr. 2008, 21:11

le but d'une clé primaire est d'identifier de manière unique un enregistrement dans la table.
Cela signifie que si tu interroge ta table en mettant la clé primaire comme condition, tu auras un seul résultat.

Pour une table d'association, c'est à dire qui associe deux tables, comme dans ton cas, il ne doit y avoir qu'une seule association entre 2 enregistrements de tes différentes tables (cf. un joueur ne peut participer qu'une seule fois à chaque jeu concours).

Pour t'assurer de ça, il suffit de mettre en place une clé primaire entre l'id du concours et l'id du joueur.

Est-ce que c'est plus clair ?

par VaN » 15 févr. 2008, 21:01

non, non, du tout ;)

Il faut que tu crées une clé primaire sur les 2 champs en même temps.

Si tu crées tes tables avec PhpMyAdmin, faut que tu supprimes l'index qui s'appelle "PRIMARY" et que tu créé un nouvel index portant sur les 2 champs portant ce nom là.
MMhh ok, je viens de le faire sous PHPmyAdmin, je me retrouve avec un tableau de ce genre, sous la structure de ma table, donc j'imagine que c'est bon :

Index
Nom de la clé | Type | Cardinalité | Champ
PRIMARY | PRIMARY | 2 | assoc_user_id, assoc_concours_id

je n'avais jamais fait ça avant. Quel est le but ?

par zeus » 15 févr. 2008, 20:44

non, non, du tout ;)

Il faut que tu crées une clé primaire sur les 2 champs en même temps.

Si tu crées tes tables avec PhpMyAdmin, faut que tu supprimes l'index qui s'appelle "PRIMARY" et que tu créé un nouvel index portant sur les 2 champs portant ce nom là.

par VaN » 15 févr. 2008, 20:22

Cela signifie que tu as, dans ta table, plusieurs enregistrements dont le champs assoc_user_id vaut 1.

Le truc que tu n'as pas compris, c'est qu'il ne faut pas une clé primaire sur assoc_concours_id, puis une autre sur assoc_user_id (soit dit en passant, avoir plusieurs clés primaires sur une table n'est pas possible, il faudrait que tu te renseignes sur ce qu'est réellement une clé primaire ;)) mais une seule clé primaire qui porte sur les 2 champs
Mhh, il me semblait bien aussi que avoir deux PK dans une table etait impossible. Si je comprend bien ce que tu dis, il faut en fait que je crée un champs assoc_id dans cette table, que je spécifie en tant que PK (et en auto increment) ?

par zeus » 15 févr. 2008, 19:58

Cela signifie que tu as, dans ta table, plusieurs enregistrements dont le champs assoc_user_id vaut 1.

Le truc que tu n'as pas compris, c'est qu'il ne faut pas une clé primaire sur assoc_concours_id, puis une autre sur assoc_user_id (soit dit en passant, avoir plusieurs clés primaires sur une table n'est pas possible, il faudrait que tu te renseignes sur ce qu'est réellement une clé primaire ;)) mais une seule clé primaire qui porte sur les 2 champs

par VaN » 15 févr. 2008, 19:51

Tu n'as pas de clé sur la table "assoc"... une clé double sur "assoc_user_id, assoc_concours_id" seraot pas mal.
C'est bien des clé primaire qu'il faut mettre sur ces deux champs ?
Oui
J'arrive bien à mettre une Primary Key sur concours_assoc_id, mais lorsque j'essaie de la mettre sur assoc_user_id, je reçois le message d'erreur suivant :
#1062 - Duplicata du champ '1' pour la clef 1
je ne le comprend pas bien.

par Truc » 15 févr. 2008, 00:36

Tu n'as pas de clé sur la table "assoc"... une clé double sur "assoc_user_id, assoc_concours_id" seraot pas mal.
C'est bien des clé primaire qu'il faut mettre sur ces deux champs ?
Oui

par VaN » 14 févr. 2008, 23:16

Pourquoi y a-t-il un champ "concours_user_id" dans la table "concours" si la table assoc doit faire le lien entre "concours" et "user" :-k
Parce que la table assoc stockent le lien entre un utilisateur et une réponse (elle stocke le fait que cet utilisateur a fait ou ignoré ce concours). Le concour_user_id lui permet de savoir quel utilisateur a enregistré ce concours dans la table CONCOURS. Ce sont donc 2 choses différentes.
Je me suis emmêlé les pinceaux, la table ASSOC stocke le fait qu'un utilisateur a fait ou ignoré un concours. On m'a conseillé de créer cette table car avant, j'enregistrais les ID des concours faits et ignorés directement dans la table USERS, dans des champs prévus à cette effet (user_concours_done et user_concours ignored), où les ID des concours etaient séparées par des ";".
Tu n'as pas de clé sur la table "assoc"... une clé double sur "assoc_user_id, assoc_concours_id" seraot pas mal.
C'est bien des clé primaire qu'il faut mettre sur ces deux champs ?
Pour ton souci manquerait bien une jointure de table avec "assoc".

Essaie avec cette requête :

Code : Tout sélectionner

SELECT concours_id FROM concours LEFT JOIN assoc ON concours_id = assoc_concours_id JOIN concours_type ON concours_type = concours_type_id JOIN sites concours_site_id = site_id WHERE concours_activated = 1 AND concours_id NOT IN (SELECT DISTINCT assoc_concours_id FROM assoc WHERE assoc_user_id = 1 )
Et concernant cette requête, bin nickel, elle fonctionne parfaitement, manquait juste un ON sur le 3e JOIN. Après correction, elle me sort bien seulement les concours ni faits, ni ignorés.

Merci beaucoup : )

par VaN » 14 févr. 2008, 01:55

Pourquoi y a-t-il un champ "concours_user_id" dans la table "concours" si la table assoc doit faire le lien entre "concours" et "user" :-k
Parce que la table assoc stockent le lien entre un utilisateur et une réponse (elle stocke le fait que cet utilisateur a fait ou ignoré ce concours). Le concour_user_id lui permet de savoir quel utilisateur a enregistré ce concours dans la table CONCOURS. Ce sont donc 2 choses différentes.
Tu n'as pas de clé sur la table "assoc"... une clé double sur "assoc_user_id, assoc_concours_id" seraot pas mal.
Ok pour ça, je vais m'en occuper.
Pour ton souci manquerait bien une jointure de table avec "assoc".

Essaie avec cette requête :

Code : Tout sélectionner

SELECT concours_id FROM concours LEFT JOIN assoc ON concours_id = assoc_concours_id JOIN concours_type ON concours_type = concours_type_id JOIN sites concours_site_id = site_id WHERE concours_activated = 1 AND concours_id NOT IN (SELECT DISTINCT assoc_concours_id FROM assoc WHERE assoc_user_id = 1 )
merci pour la réponse, je test ça demain soir et te tiens au courant, la je vais me coucher.

par Truc » 13 févr. 2008, 23:10

Pourquoi y a-t-il un champ "concours_user_id" dans la table "concours" si la table assoc doit faire le lien entre "concours" et "user" :-k

Tu n'as pas de clé sur la table "assoc"... une clé double sur "assoc_user_id, assoc_concours_id" seraot pas mal.

Pour ton souci manquerait bien une jointure de table avec "assoc".

Essaie avec cette requête :

Code : Tout sélectionner

SELECT concours_id FROM concours LEFT JOIN assoc ON concours_id = assoc_concours_id JOIN concours_type ON concours_type = concours_type_id JOIN sites concours_site_id = site_id WHERE concours_activated = 1 AND concours_id NOT IN (SELECT DISTINCT assoc_concours_id FROM assoc WHERE assoc_user_id = 1 )

par VaN » 13 févr. 2008, 20:49

up du topic, pour mettre le flag 'new post' pour les connaisseurs SQL qui trainent sur ce forum, car j'ai édité mon message, depuis mon dernier post.

Soit dit en passant, le système anti-spam (pas pouvoir répondre si on est l'auteur du dernier post) est parfois très embêtant, car en éditant un message, on apporte parfois pleins d'infos supplémentaires, mais le msg ne passe pas en 'new post'.

[Note : ce message a été posté de manière anonyme avant d'être réattribué à son auteur]

par VaN » 12 févr. 2008, 17:19

mhh je ne connaissais ni NOT IN, ni l'imbrication de requête. merci, je vais aller voir de ce côté.

EDIT :

Alors, j'ai un peu modifié la requête. Elle me sort bien le concours (le seul) qui correspond aux critères que j'ai cité plus haut (ni fait, ni ignoré), mais elle me le sort en 2 exemplaires. Pourquoi donc ?
<?php
$sql = "SELECT concours_id, site_name, concours_end_date, concours_type_title, concours_rating 
FROM concours, concours_type, sites, assoc 
WHERE concours_type = concours_type_id 
AND concours_site_id = site_id 
AND concours_activated = 1 
AND concours_id NOT IN (SELECT DISTINCT assoc_concours_id FROM assoc WHERE assoc_user_id = '".$_GET['user_id']."')"; ?>

par d0m » 12 févr. 2008, 16:50

Tu peux utiliser une sous requête :
Sélectionner les concours qui ne sont pas dans la table assoc :

Code : Tout sélectionner

SELECT concours_id,.... FROM concours WHERE concours_id NOT IN (SELECT DISTINCT concours_id FROM assoc)

Requête un peu compliquée

par VaN » 12 févr. 2008, 16:41

Bonjour,

j'ai une table CONCOURS, une TABLES USERS, et une TABLE ASSOC, que voici :
CREATE TABLE `concours` (
`concours_id` int(11) NOT NULL auto_increment,
`concours_user_id` int(11) NOT NULL,
`concours_site_id` int(11) NOT NULL,
`concours_url` text NOT NULL,
`concours_reglement_url` text NOT NULL,
`concours_start_date` datetime NOT NULL,
`concours_end_date` datetime NOT NULL,
`concours_type` tinyint(4) NOT NULL,
`concours_participation` tinyint(11) NOT NULL,
`concours_qs` enum('Oui','Non') NOT NULL,
`concours_nb_reponses` tinyint(4) NOT NULL,
`concours_lots` text NOT NULL,
`concours_rating` tinyint(4) NOT NULL,
`concours_activated` tinyint(4) NOT NULL,
PRIMARY KEY (`concours_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;

CREATE TABLE `users` (
`user_id` int(11) NOT NULL auto_increment,
`user_login` text character set latin1 collate latin1_general_cs NOT NULL,
`user_pass` text character set latin1 collate latin1_general_cs NOT NULL,
`user_mail` text NOT NULL,
`user_level` tinyint(4) NOT NULL,
`user_activated` tinyint(4) NOT NULL,
`user_activation_key` text character set latin1 collate latin1_general_cs NOT NULL,
`user_logged` tinyint(4) NOT NULL,
`user_last_session` datetime NOT NULL,
`user_last_ip` text NOT NULL,
`user_points` int(11) NOT NULL,
`user_parrain_id` int(11) NOT NULL,
`user_scoot_activated` tinyint(4) NOT NULL,
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=24 ;

CREATE TABLE `assoc` (
`assoc_user_id` int(11) NOT NULL,
`assoc_concours_id` int(11) NOT NULL,
`assoc_statut` enum('','done','ignored') NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
je souhaiterai afficher la liste des concours, pour un utilisateur donné (j'ai son $_SESSION['user_id']), qui n'ont pas de correspondance dans la table ASSOC. Cette table ASSOC sert à savoir si un utilisateur à fait/ignoré un concours. Lorsque l'utilisateur fait cette requete, cela ajoute une entrée dans la table, avec le concours_id, le user_id, et le statut ('done', 'ignored').

La, j'aimerai qu'une requete sortent tous les concours qui ne sont ni faits, ni ignorés, donc qui n'ont pas encore de correspondance dans la table ASSOC.

j'en suis pour le moment à la, mais je bloque sur la fin de la requete :
$sql = 	"SELECT concours_id, site_name, concours_end_date, concours_type_title, concours_rating
			FROM ".$prefixe."concours, ".$prefixe."concours_type, ".$prefixe."sites, ".$prefixe."assoc
			WHERE concours_type = concours_type_id
			AND concours_site_id = site_id
			AND concours_id = assoc_concours_id
			AND concours_activated = 1
			AND assoc_user_id = '".$_GET['user_id']."'";