Comment faire fonctionner une requête imbriquée dans un where

Résolu/Fermé
Matarela Messages postés 9 Date d'inscription lundi 30 septembre 2013 Statut Membre Dernière intervention 29 janvier 2014 - Modifié par Matarela le 14/10/2013 à 12:26
Reivax962 Messages postés 3672 Date d'inscription jeudi 16 juin 2005 Statut Membre Dernière intervention 11 février 2021 - 15 oct. 2013 à 11:26
Bonjour,

J'aimerai savoir si il est possible de faire fonctionner un SELECT imbriqué dans un WHERE.
Voici la requête SQL que je souhaite faire directement fonctionner dans ma base de données,

SELECT * 
FROM ( SELECT t1.community, t1.n_days FROM ( select CONCAT(SUBSTR(cp,8,8),SUBSTRING_INDEX(SUBSTRING_INDEX(cp, '/', -2), '/', 1)) as community, DATEDIFF(now(), last_at) as n_days FROM box) t1
inner join community on t1.community = community.community) T
WHERE T.community not in ( select community from T where n_days < 180);

Pour être plus précis, cette requête SQL veut afficher toutes les colonnes se trouvant dans la table T, cette table T est créée grâce au premier SELECT imbriqué qui lui souhaite afficher la communauté et le nombre de jours (qui sont créés dans la requête imbriqué, celle-ci select CONCAT(SUBSTR(cp,8,8),SUBSTRING_INDEX(SUBSTRING_INDEX(cp, '/', -2), '/', 1)) as community, DATEDIFF(now(), last_at) as n_days FROM box. Le cp ressemble à ça mail0/lssu/x/y/xy/pseudo pour devenir après la concaténation lssu/xy et last_at est une date qui devient un nombre de jour après avoir fait la différence après la date actuelle. (Compliqué tout ça))

En gros la table t1 donne ça

----------------------------
| community | n_days |
----------------------------
| lssu/gama | 255 |
| lssu/gama | 2 |
| lssu/emau | 102 |
| lssu/mou | 190 |
----------------------------

Ensuite on souhaite faire une comparaison avec une autre table nommée community avec un inner join et on nomme l'ensemble T.
Pour le moment tout fonctionne parfaitement et donne ce que je souhaite.
Mais le problème vient après et plus précisément ici where T.community not in ( select community from T where n_days < 180); Je souhaite prendre toutes les communautés n'ayant aucun nombre de jours inférieur à 180, c'est à dire que dans l'exemple ci-dessus, seul "lssu/mou" sera affiché (après exécution de la requête entière) car "lssu/gama" comporte une communauté avec au moins un nombre de jour inférieur à 180. (Oui j'ai parfois du mal à me comprendre moi-même mais c'est la seule manière de l'expliquer).

J'aimerai donc savoir si il est possible qu'en une seule requête je puisse obtenir "lssu/mou" avec son nombre de jour. Quand j'essaye d'exécuter la commande, unix me renvoie un message d'erreur ERROR 1146 (42S02): Table 'box.T' doesn't exist.

Merci d'avance pour votre aide et n'hésitez pas à me poser des questions pour plus de précision.

Matarela

PS : pour préciser, j'ai la version 4.1.11 de mysql

2 réponses

salut,

je ne vais pas reprendre ta requête car elle me semble bien compliquée pour ce que tu souhaite. Cependant, sache qu'une table non temporaire peu être déclarée plusieurs fois dans une requête. (je ne vais l'utiliser qu'une fois, mais ca peu être utile à savoir tout de même)

Donc dans un premier temps, on va éliminer de tes résultats ce qui ne nous interesse pas. T1 sera donc déclaré de cette manière :


(
select community ,
max(n_day) as n_days
FROM
(
select CONCAT(SUBSTR(cp,8,8),SUBSTRING_INDEX(SUBSTRING_INDEX(cp, '/', -2), '/', 1)) as community, DATEDIFF(now(), last_at) as n_day
FROM box
)
) as T1

ce qui retournera :

----------------------------
| community | n_days |
----------------------------
| lssu/gama | 255 |
| lssu/emau | 102 |
| lssu/mou | 190 |
----------------------------

doncil te suffit de rajouter

where n_days < 180;

pour avoir les résultats que tu attends

naga
0
Reivax962 Messages postés 3672 Date d'inscription jeudi 16 juin 2005 Statut Membre Dernière intervention 11 février 2021 1 011
15 oct. 2013 à 11:26
Autre solution : tu peux aussi mettre ton WHERE à l'intérieur de ta première sous-requête, ce qui en plus enlève un niveau de sous-requête et cimplifie le tout :
SELECT t1.community, t1.n_days
FROM (
select
CONCAT(SUBSTR(cp, 8, 8), SUBSTRING_INDEX(SUBSTRING_INDEX(cp, '/', -2), '/', 1)) as community,
DATEDIFF(now(), last_at) as n_days
FROM box
WHERE DATEDIFF(now(), last_at) >= 180
) t1
inner join community on t1.community = community.community;

Xavier

PS : on peut encore enlever un niveau de sous-requête, mais je ne suis pas sûr que ça rende plus lisible :

SELECT com.community, DATEDIFF(now(), box.last_at) as n_days
FROM box
INNER JOIN community com
ON CONCAT(SUBSTR(box.cp, 8, 8), SUBSTRING_INDEX(SUBSTRING_INDEX(box.cp, '/', -2), '/', 1)) = com.community
WHERE DATEDIFF(now(), box.last_at) >= 180
0