Comment faire fonctionner une requête imbriquée dans un where
Résolu
Matarela
Messages postés
9
Date d'inscription
Statut
Membre
Dernière intervention
-
Reivax962 Messages postés 3672 Date d'inscription Statut Membre Dernière intervention -
Reivax962 Messages postés 3672 Date d'inscription Statut Membre Dernière intervention -
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,
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
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
A voir également:
- Requete imbriquée sql
- Liste imbriquée excel - Guide
- Logiciel sql - Télécharger - Bases de données
- Sql lister les tables ✓ - Forum Programmation
- Requête bloquée par le pare-feu applicatif claranet webfence ✓ - Forum Réseaux sociaux
- Jointure sql ✓ - Forum 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 :
ce qui retournera :
doncil te suffit de rajouter
pour avoir les résultats que tu attends
naga
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
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 :
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 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