par
Hubert Roksor » 19 nov. 2007, 10:27
Ok, donc pour l'exemple on va dire que tu veux récupérer toutes les photos du groupe 1 et la photo la plus récente des autres groupes. SQL ne permet pas de faire un peu de GROUP BY par ci et un peu de "je récupère tout" par là, mais ce n'est pas un problème : il suffit de récupérer la première moitié dans une requête puis le reste dans une autre. Mieux encore, on peut utiliser UNION pour récupérer les deux résultats l'un à la suite de l'autre.
Pour en revenir à la requête en question, il n'existe malheureusement pas dans SQL de méchanisme pour récupérer l'enregistrement possédant le plus grand X pour chaque groupe. Ça ne veut pas dire que c'est impossible, c'est juste un peu plus long à écrire.
Ce que SQL permet, c'est de récupérer la plus grande valeur de X pour chaque groupe. Par exemple:
Code : Tout sélectionner
SELECT id_photo_groupe, MAX(date_in) AS date_in
FROM photos
WHERE id_photo_groupe <> 1
GROUP BY id_photo_groupe
J'appellerai ce résultat
tmp1. On a donc pour chaque groupe la date la plus récente. On peut savoir à quel(s) enregistrement(s) chaque date de chaque groupe correspond à l'aide d'une jointure. Et puisqu'il est théoriquement possible que plusieurs photos soient uploadées au même moment, on ne récupère que le numéro d'enregistrement
id_photo de chaque date de chaque groupe
Code : Tout sélectionner
SELECT MAX(p1.id_photo) AS id_photo
FROM
(
SELECT id_photo_groupe, MAX(date_in) AS date_in
FROM photos
WHERE id_photo_groupe <> 1
GROUP BY id_photo_groupe
) AS tmp1
JOIN photos p1 USING (id_photo_groupe, date_in)
GROUP BY p1.id_photo_groupe
Ce qui nous donne le résultat
tmp2, correspondant à l'identifiant
id_photo de chaque groupe. Maintenant que l'on a un identifiant et que l'on n'a plus à grouper les résultat, on peut récupérer le reste des informations dont on a besoin à l'aide d'une dernière jointure, ce qui nous donne toutes les données de la photo la plus récente dans chaque groupe.
Code : Tout sélectionner
SELECT p2.*
FROM
(
SELECT MAX(p1.id_photo) AS id_photo
FROM
(
SELECT id_photo_groupe, MAX(date_in) AS date_in
FROM photos
WHERE id_photo_groupe <> 1
GROUP BY id_photo_groupe
) AS tmp1
JOIN photos p1 USING (id_photo_groupe, date_in)
GROUP BY p1.id_photo_groupe
) AS tmp2
JOIN photos p2 USING (id_photo)
La dernière étape qui consiste à adjoindre les informations de toutes les photos du groupe sélectionné, ce qui nous donne
Code : Tout sélectionner
(
SELECT *
FROM photos
WHERE id_photo_groupe = 1
)
UNION ALL
(
SELECT p2.*
FROM
(
SELECT MAX(p1.id_photo) AS id_photo
FROM
(
SELECT id_photo_groupe, MAX(date_in) AS date_in
FROM photos
WHERE id_photo_groupe <> 1
GROUP BY id_photo_groupe
) AS tmp1
JOIN photos p1 USING (id_photo_groupe, date_in)
GROUP BY p1.id_photo_groupe
) AS tmp2
JOIN photos p2 USING (id_photo)
)
Pour des questions de performance, n'oublie pas d'ajouter un index sur
(id_photo_groupe,date_in)
Code : Tout sélectionner
CREATE INDEX date_par_groupe ON photos (id_photo_groupe, date_in)
Ok, donc pour l'exemple on va dire que tu veux récupérer toutes les photos du groupe 1 et la photo la plus récente des autres groupes. SQL ne permet pas de faire un peu de GROUP BY par ci et un peu de "je récupère tout" par là, mais ce n'est pas un problème : il suffit de récupérer la première moitié dans une requête puis le reste dans une autre. Mieux encore, on peut utiliser UNION pour récupérer les deux résultats l'un à la suite de l'autre.
Pour en revenir à la requête en question, il n'existe malheureusement pas dans SQL de méchanisme pour récupérer l'enregistrement possédant le plus grand X pour chaque groupe. Ça ne veut pas dire que c'est impossible, c'est juste un peu plus long à écrire.
Ce que SQL permet, c'est de récupérer la plus grande valeur de X pour chaque groupe. Par exemple:
[code] SELECT id_photo_groupe, MAX(date_in) AS date_in
FROM photos
WHERE id_photo_groupe <> 1
GROUP BY id_photo_groupe[/code]
J'appellerai ce résultat [i]tmp1[/i]. On a donc pour chaque groupe la date la plus récente. On peut savoir à quel(s) enregistrement(s) chaque date de chaque groupe correspond à l'aide d'une jointure. Et puisqu'il est théoriquement possible que plusieurs photos soient uploadées au même moment, on ne récupère que le numéro d'enregistrement [i]id_photo[/i] de chaque date de chaque groupe
[code] SELECT MAX(p1.id_photo) AS id_photo
FROM
(
SELECT id_photo_groupe, MAX(date_in) AS date_in
FROM photos
WHERE id_photo_groupe <> 1
GROUP BY id_photo_groupe
) AS tmp1
JOIN photos p1 USING (id_photo_groupe, date_in)
GROUP BY p1.id_photo_groupe[/code]
Ce qui nous donne le résultat [i]tmp2[/i], correspondant à l'identifiant [i]id_photo[/i] de chaque groupe. Maintenant que l'on a un identifiant et que l'on n'a plus à grouper les résultat, on peut récupérer le reste des informations dont on a besoin à l'aide d'une dernière jointure, ce qui nous donne toutes les données de la photo la plus récente dans chaque groupe.
[code] SELECT p2.*
FROM
(
SELECT MAX(p1.id_photo) AS id_photo
FROM
(
SELECT id_photo_groupe, MAX(date_in) AS date_in
FROM photos
WHERE id_photo_groupe <> 1
GROUP BY id_photo_groupe
) AS tmp1
JOIN photos p1 USING (id_photo_groupe, date_in)
GROUP BY p1.id_photo_groupe
) AS tmp2
JOIN photos p2 USING (id_photo)[/code]
La dernière étape qui consiste à adjoindre les informations de toutes les photos du groupe sélectionné, ce qui nous donne
[code](
SELECT *
FROM photos
WHERE id_photo_groupe = 1
)
UNION ALL
(
SELECT p2.*
FROM
(
SELECT MAX(p1.id_photo) AS id_photo
FROM
(
SELECT id_photo_groupe, MAX(date_in) AS date_in
FROM photos
WHERE id_photo_groupe <> 1
GROUP BY id_photo_groupe
) AS tmp1
JOIN photos p1 USING (id_photo_groupe, date_in)
GROUP BY p1.id_photo_groupe
) AS tmp2
JOIN photos p2 USING (id_photo)
)[/code]
Pour des questions de performance, n'oublie pas d'ajouter un index sur [i](id_photo_groupe,date_in)[/i]
[code]CREATE INDEX date_par_groupe ON photos (id_photo_groupe, date_in)[/code]