Salut,

Le titre parait simple mais il n'y a pas beaucoup de place

J'ai donc un forum, avec un système de lu/non lu. Individuellement (sur chaque sujet), le système fonctionne bien.
Le soucis, c'est que je souhaite qu'un utilisateur puisse savoir s'il a des messages non-lus depuis l'accueil, et ce, pour chaque forum.
Pour corser la chose, l'utilisateur a un lien "Marquer tous les forums comme lus"; lorsqu'il appuie dessus, sa "date de dernière lecture de tout le forum" est mise à jour dans la base de données.

Pour compter le nombre de sujets non-lus depuis cette dernière date (enfin, savoir qu'il y en a au moins un me suffit), je suis partit du principe que
Code : Sélectionner tout - Visualiser dans une fenêtre à part
nonVus = ("Nombre de topics avec un message plus récent que la date" - "Nombre de topics lus dont le dernier message est plus récent que la date"
J'en ai déduit la requête SQL suivante :
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
SELECT f.id, f.nom, f.description, f.niv_acces, f.parent, f.totalTopics, f.totalPosts, f.lastPostId, f.`order`,
	((
		SELECT COUNT(t.id)
		FROM topics t
		WHERE (SELECT p.date FROM posts p WHERE p.id = t.lastPostId) > "2011-09-13 23:32:30"
			AND t.forumId = f.id
	) - (
		SELECT COUNT(t.id)
		FROM topics t
		LEFT JOIN vues v ON t.id = v.id_topic
		WHERE (SELECT p.date FROM posts p WHERE p.id = t.lastPostId) > "2011-09-13 23:32:30"
			AND v.id_lastpost = t.lastPostId
			AND v.id_m = 479
			AND t.forumId = f.id
	)) AS nonlus
FROM forums f
ORDER BY f.`order`, f.`id`;
(Exemple pour l'utilisateur N° 479 qui a marqué tous les forums comme lus le 13 septembre 2011 à 23h32:30)
Le problème, c'est qu'elle n'est pas optimisée du tout, 0.306s contre 0.001s sans le nonlus.

Ma base de données ressemble à cela :

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
CREATE TABLE `forums` (
  `id` mediumint(8) NOT NULL AUTO_INCREMENT,
  `nom` varchar(50) NOT NULL,
  `description` varchar(255) DEFAULT NULL,
  `parent` mediumint(8) DEFAULT NULL,
  `lastPostId` mediumint(8) DEFAULT NULL,
  `order` tinyint(3) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=latin1;
CREATE TABLE `posts` (
  `id` mediumint(8) NOT NULL AUTO_INCREMENT,
  `topicId` mediumint(8) NOT NULL,
  `forumId` mediumint(8) NOT NULL,
  `titre` varchar(73) NOT NULL,
  `auteur` mediumint(8) NOT NULL,
  `date` datetime NOT NULL,
  `texte` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26940 DEFAULT CHARSET=latin1;
 
CREATE TABLE `topics` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `forumId` mediumint(8) unsigned NOT NULL,
  `titre` varchar(70) NOT NULL,
  `sousTitre` varchar(70) NOT NULL,
  `firstPostID` mediumint(8) unsigned NOT NULL,
  `lastPostId` mediumint(8) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2273 DEFAULT CHARSET=latin1;
 
CREATE TABLE `utilisateurs` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `pseudo` varchar(25) NOT NULL,
  `password` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `readAllDate` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2170 DEFAULT CHARSET=latin1;
 
CREATE TABLE `vues` (
  `id_m` mediumint(8) NOT NULL,
  `id_topic` mediumint(8) NOT NULL,
  `id_forum` mediumint(8) NOT NULL,
  `id_lastpost` mediumint(8) NOT NULL,
  PRIMARY KEY (`id_m`,`id_topic`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
J'ai simplifié la table pour qu'elle ne contienne en principe que ce qui est nécessaire. Si quelque chose n'est pas clair pour vous dans la table, je me ferais un plaisir de vous aider (puis vous m'aidez )

Du coup, je me demande si vous avez des idées pour optimiser, ou d'autres manières de faire que la mienne.

Mika.