Requête mysql

Résolu
Aelindor Messages postés 6 Date d'inscription samedi 7 avril 2007 Statut Membre Dernière intervention 1 décembre 2007 - 1 déc. 2007 à 00:23
Aelindor Messages postés 6 Date d'inscription samedi 7 avril 2007 Statut Membre Dernière intervention 1 décembre 2007 - 1 déc. 2007 à 18:44
Bonsoir,

j'ai un problème très embêtant avec ma requête, donc voici la tête:

SELECT c.read_by, u.id_user, GROUP_CONCAT(DISTINCT u.login SEPARATOR ", ") AS read_by
FROM contact c, user u
WHERE c.id_contact =1
AND u.id_user IN ( c.read_by )
GROUP BY c.id_contact


c.read_by est du type string qui est une suite de chiffre séparé par des virgules: "1,3,4,8,(etc...)"
Mon problème est en fait que ce champ est du type string !
Car pour faire fonctionner ma requête, plus particulièrement le IN (), il faut que ce soit comme cet exemple :

SELECT c.read_by, u.id_user, GROUP_CONCAT(DISTINCT u.login SEPARATOR ", ") AS read_by
FROM contact c, user u
WHERE c.id_contact =1
AND u.id_user IN ( 1,3,4,8,(etc...) )
GROUP BY c.id_contact


Donc ma question est, comment faire pour transformer un string : "1,3,4,8" en un type non string de la forme : 1,3,4,8 (sans les guillemets particulier du string)
Un type float ou decimal ne règle pas le problème car seulement ce qu'il y a après la première virgule est gardé...
Si vous avez une idée... merci d'avance :/

10 réponses

neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
1 déc. 2007 à 14:20
Re,

Vais essayer de comprendre ce que tu veux...
Si je comprends bien, il y a plusieurs admins sur ton site, et tu souhaites pouvoir savoir qui a lu/répondu aux messages postés dans un formulaire de contact.

Si c'est bien ça, je pense que tu ne prends pas les choses dans le bon sens. Personnellement, je ne ferais pas comme ça.
J'aurais effectivement une table pour stocker les messages, mais j'en aurais deux de plus pour savoir qui a lu/répondu.

contact
-----------
id_contact
titre
date
...

contact_read
---------------
id_contact
id_user
date_read


contact_answered
-------------------
id_answer
id_contact
id_user
date_answer
text_answer

Pour savoir qui a lu un message d'id 3 par exemple :

SELECT u.id_user, u.pseudo, cr.date_read
FROM contact_read cr
LEFT JOIN users u
ON u.id_user=cr.id_user
WHERE cr.id_contact=3
GROUP BY u.id_user;

Pour connaitre la réponse qui a été faite, même genre de requête :

SELECT u.id_user, u.pseudo, ca.date_answer, ca.text_answer
FROM contact_answered ca
LEFT JOIN users u
ON ca.id_user=u.id_user
WHERE ca.id_contact=3
GROUP BY u.id_user;

Je trouve cette manière de faire non seulement plus efficace, mais surtout plus conforme à ce qu'aurait donné une analyse du problème avec Merise.
3
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
1 déc. 2007 à 15:33
J'avais presque terminé mon message quand mon pc a décidé de redémarrer tout seul... pffffffff...

Je comprends ta réticence vis à vis d'un nombre important de tables, pour avoir déjà eu la même. Cependant, si le fait de vouloir limiter le nombre de tables est pertinent du point de vue de l'humain (plus facile de s'y retrouver dans son interface de gestion type phpMyAdmin), cela n'a aucun sens du point de vue de la machine.

Chercher dans un champ texte une valeur à extraire (ce qui implique des traitements de la chaine avant de pouvoir comparer) est bien plus coûteux en performances qu'une recherche sur deux tables bien indexées.

Et puis je sais plus ce que j'avais écrit d'autre... mpff :/
N'hésite pas à te renseigner sur Merise, y'a de très bons bouquin sur le sujet (chez O'Reilly et Eyrolles notamment) : c'est un outil puissant d'analyse qui n'a pas la notoriété qu'il mérite.

Jette aussi un oeil sur l'optimisation des requêtes par MySQL :
http://dev.mysql.com/doc/refman/5.0/fr/query-speed.html
3
cs_lowkey Messages postés 260 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 5 novembre 2010 1
1 déc. 2007 à 00:50
Salut !!

SELECT c.read_by, u.id_user
FROM contact c, user u
WHERE c.id_contact =1
AND u.id_user IN ( SELECT u.login FROM user u )
GROUP BY c.id_contact

Je l'ai pas testé, mais ça parait ok, non?

<hr />
lowkey
0
Aelindor Messages postés 6 Date d'inscription samedi 7 avril 2007 Statut Membre Dernière intervention 1 décembre 2007
1 déc. 2007 à 01:14
malheureusement non j'ai déjà essayé ça :/ voilà ce que ça me donne comme résultat:
read_by |, id_user |ready |----
1,3,4, , 1, Blackelf

la requête était:

SELECT c.read_by, u.id_user, GROUP_CONCAT(DISTINCT u.login SEPARATOR ", ") AS ready
FROM contact c, user u
WHERE c.id_contact =1
AND u.id_user IN ( SELECT c.read_by FROM contact c)
GROUP BY c.id_contact

alors que moi je souhaite ceci :
read_by |id_user |ready |----
1,3,4, 1, Blackelf, Pseudo2, Pseudo3

(les chiffres du champ read_by correspondent chacun à l'id d'un membre dans ma table user).
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_lowkey Messages postés 260 Date d'inscription jeudi 31 mai 2007 Statut Membre Dernière intervention 5 novembre 2010 1
1 déc. 2007 à 02:49
SELECT c.read_by, u.id_user, GROUP_CONCAT(DISTINCT u.login SEPARATOR ", ") AS ready
FROM contact c, user u
WHERE c.id_contact =1
AND u.id_user IN ( SELECT c.read_by FROM contact c)
GROUP BY c.id_contact

Tu fait un group by sur un champ qui n'est pas dans ton select => pas bon.
Si tu nous mettais la structure de tes tables, ce serait plus simple

<hr />
lowkey
0
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
1 déc. 2007 à 11:55
Salut,

"Tu fait un group by sur un champ qui n'est pas dans ton select => pas bon."
Pas vrai du tout. On peut tout à fait faire un group_by sur un champ caché.

Cela dit, je rejoins lowket sur le fait qu'avec la structure des tables, c'est plus facile. Et puis dis nous concrètement ce que tu cherches à faire, c'est plus facile pour comprendre et te proposer une solution que tu n'as peut-être pas envisagée.
0
Aelindor Messages postés 6 Date d'inscription samedi 7 avril 2007 Statut Membre Dernière intervention 1 décembre 2007
1 déc. 2007 à 11:56
ben, si ça peut aider les voila:

CREATE TABLE `contact` (
  `id_contact` int(11) NOT NULL auto_increment,
  `timestamp` int(21) NOT NULL default '0',
  `author` varchar(255) collate latin1_general_ci NOT NULL,
  `title` varchar(255) collate latin1_general_ci NOT NULL,
  `email` varchar(255) collate latin1_general_ci NOT NULL default '',
  `category` tinyint(3) default NULL,
  `message` text collate latin1_general_ci NOT NULL,
  `status` varchar(10) collate latin1_general_ci NOT NULL default '',
  `answer` varchar(11) collate latin1_general_ci NOT NULL,
  `read_by` varchar(255) collate latin1_general_ci default NULL,
  `answered_by` varchar(255) collate latin1_general_ci default NULL,
  `timestamp_read` varchar(255) collate latin1_general_ci default NULL,
  `timestamp_answer` varchar(255) collate latin1_general_ci default NULL,
  KEY `id_contact` (`id_contact`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=4 ;

--
-- Contenu de la table `contact`
--

INSERT INTO `contact` (`id_contact`, `timestamp`, `author`, `title`, `email`, `category`, `message`, `status`, `answer`, `read_by`, `answered_by`, `timestamp_read`, `timestamp_answer`) VALUES
(1, 108388607, 'Blackelf', 'Titre de test', 'email@email.fr', 0, 'Texte texte texte ...', 'lu', 'repondu', '1,3,4,', '1,4,', '1196370986,1196371186,1196371186,', '1196370986,1196371186,'),
(2, 108388607, 'Blackelf', 'Test2', 'bj.delorme@free.fr', 0, 'blablabla', 'lu', 'repondu', '3,1,', '3,', '1196370986,1196371186,', '1196370986,')

CREATE TABLE `user` (
  `id_user` int(11) NOT NULL auto_increment,
  `timestamp` bigint(21) NOT NULL default '0',
  `login` varchar(255) collate latin1_general_ci NOT NULL,
  `password` varchar(255) collate latin1_general_ci NOT NULL default '',
  `email` varchar(255) collate latin1_general_ci NOT NULL default '',
  `email_instant` varchar(255) collate latin1_general_ci NOT NULL,
  `birthdate` bigint(21) NOT NULL,
  `avatar` varchar(255) collate latin1_general_ci NOT NULL default '',
  `sexe` char(10) collate latin1_general_ci NOT NULL,
  `droits` int(2) NOT NULL default '0',
  `language` char(10) collate latin1_general_ci NOT NULL,
  `status` tinyint(2) NOT NULL default '2',
  KEY `id_user` (`id_user`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=6 ;

--
-- Contenu de la table `user`
--

INSERT INTO `user` (`id_user`, `timestamp`, `login`, `password`, `email`, `email_instant`, `birthdate`, `avatar`, `sexe`, `droits`, `language`, `status`) VALUES
(1, 1174239305, 'Blackelf', '5f4dcc3b5aa765d61d8327deb882cf99', 'email@email.fr', '', 1189980000, 'blackelf.gif', 'Homme', 3, 'fr', 1),
(3, 1189296137, 'Junkan', '47c6b15aca93873f58522f26300d181d', 'cuicui@hotmail.com', '', 1189980000, 'avatar.jpg', 'Femme', 3, 'fr', 1)

Je n'ai pas mis toutes les entrées mais 2 suffisent pour comprendre comment ça marche.
Merci de vous pencher sur la question en tout cas
0
Aelindor Messages postés 6 Date d'inscription samedi 7 avril 2007 Statut Membre Dernière intervention 1 décembre 2007
1 déc. 2007 à 12:03
Ce que je souhaite obtenir c'est d'afficher à la lecture du message dans mon administration la ligne suivante :
"Ce message a déjà été lu par Blackelf, Pseudo2, Pseudo3 (etc...), le Mercredi 17 (etc...)"
Bien sûr, je sais très bien que je pourrais faire ça en 2 requêtes et c'est fini mais pourtant je suis sûr qu'il y a moyen de le faire en une requête, j'y suis arrivé en faisant comme ça dans mysql:
SELECT c.read_by, u.id_user, GROUP_CONCAT(DISTINCT u.login SEPARATOR ", ") AS read_by
FROM contact c, user u
WHERE c.id_contact =1
AND u.id_user IN ( 1,3,4 )
GROUP BY c.id_contact

Ici le IN fonctionne parfaitement bien et me renvoie ce que je veux, mais quand je remplace par le champ c.read_by, là ça ne marche pas alors que c'est la même chose (mais de type varchar).
0
Aelindor Messages postés 6 Date d'inscription samedi 7 avril 2007 Statut Membre Dernière intervention 1 décembre 2007
1 déc. 2007 à 14:50
Merci de ta réponse,

en effet tu as parfaitement compris ce que j'essaye de faire.
Il est clair que ta méthode est beaucoup plus clair, seulement j'ai pris l'habitude d'avoir un nombre de table restreint pour chaque module que je créer, car là si on compte ça fait 3 tables différentes +1 externe pour réaliser ce que je veux.
Moi ça me parait beaucoup et de ce fait moins efficace, mais je dois très certainement me tromper, je ne suis pas du tout expert dans le domaine donc bon... d'ailleurs le terme Merise m'était inconnu jusqu'à maintenant, wikipédia m'a renseigné et je vais tacher d'en apprendre un peu plus...
Donc je pense que je vais faire comme tu le pense, je me disais que c'était mieux de faire une table regroupant toute les infos concernant un message et son suivi mais bon ce n'est finalement peut-être pas le cas :/
Merci de ton aide, j'attends ta réponse et je met le sujet en résolu.
0
Aelindor Messages postés 6 Date d'inscription samedi 7 avril 2007 Statut Membre Dernière intervention 1 décembre 2007
1 déc. 2007 à 18:44
Ok je comprend, merci de ton aide, je vais travailler dans ce sens là :)
A bientôt!
0
Rejoignez-nous