SQLPro, merci pour ton aide.
Peux-tu me décrire ce que fais cette requête, je ne suis pas certain de comprendre ? Merci.
P.S : plus spécifiquement cette jointure : AND T1.MonAppart = T2.monApprt
Version imprimable
SQLPro, merci pour ton aide.
Peux-tu me décrire ce que fais cette requête, je ne suis pas certain de comprendre ? Merci.
P.S : plus spécifiquement cette jointure : AND T1.MonAppart = T2.monApprt
Aidez-moi SVP
Il faut que je parvienne à faire une requête qui liste tous les appartements qui ont au moins une date libre entre les 2 dates.
Effectivement, j'avais pas pensé à ce cas.Citation:
La requête que tu me propose skuatamad n'est pas correcte car un appartement peut être réservé du 28 aout au 2 septembre puis du 3 septembre au 28 septembre.
J'ai revu ma requête et ça pourrait donné quelque chose comme ça (j'ai fait quelques tests, mais bon sûrement pas assez...) :
Par contre j'ai pas intégré OR ResaDebut IS NULL, présent dans ta requête parceque je sais pas bien à quoi ça correspond.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 select a.AppartId from appartement a where not exists (select 1 from (/*Liste des apparts loués sur la période curdate -> curdate+30*/ select AppartId,min(d1) as deb, max(d4) as fin from ( select a.AppartId, a.ResaDebut as d1, a.ResaFin as d2, b.ResaDebut as d3, b.ResaFin as d4 from reservation a INNER JOIN reservation b ON (a.AppartId=b.AppartId AND b.ResaDebut BETWEEN a.ResaFin AND a.ResaFin+1) /*a.ResaFin+1 ou +n, n étant le nb de jours considérés comme trop petit pour permettre une réservation*/ ) having min(d1)<=curdate and max(d4) >= curdate+30 group by AppartId ) pas_dispo where pas_dispo.AppartId=a.AppartId )
Autre chose, gare aux heures des dates lors des comparaisons (>= curdate+30 ou a.ResaFin+1), sous oracle j'utilise trunc pour ne garder que jour/mois/annee, mais je sais pas si ça existe avec mysql.
Bon, c'est peut être inutilement compliqué, mais j'ai pas trouvé plus simple, et ça me semble quand même plus propre qu'une liste de OR (enfin si ça marche évidemment.)
J'espère que niveau perf ça ira, sinon tu peux tester avec NOT IN.
Pour la suite de ta problématique, continue à jongler avec les EXISTS/NOT EXISTS, comme te l'a montré SQLpro.
Pour ton PS, lis ça : http://sqlpro.developpez.com/cours/s...quetes/#L1.5.1
[EDIT] désolé je m'étais planté de requête à poster :aie:
J'en suis arrivé là :
Pour les perf. ca risque d'être difficile, vraiment difficile.Code:
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 SELECT a.AppartId, MIN(r1.ResaFin) as Debut, MIN(r2.ResaDebut) as Fin FROM appartement a LEFT OUTER JOIN reservation r1 ON a.AppartId=r1.AppartId LEFT OUTER JOIN reservation r2 ON r1.AppartId=r2.AppartId WHERE /* LISTE LES APPARTEMENTS QUI ONT AU MINIMUM UNE PLACE PENDANT LA PERIODE */ ( a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-08-29' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-08-30' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-08-31' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-09-01' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-09-02' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-09-03' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-09-04' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-09-05' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-09-06' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-09-07' BETWEEN ResaDebut AND ResaFin) OR a.AppartId NOT IN (SELECT r.AppartId FROM reservation r WHERE '2008-09-08' BETWEEN ResaDebut AND ResaFin) ) /* OBJECTIF : INDIQUER LES DATES DES RESERVATIONS ACTUELLES LES PLUS PROCHE DE LA PERIODE */ AND (r1.ResaFin <= '2008-09-08' AND r1.ResaFin >='2008-08-28' AND r2.ResaDebut >= '2008-08-28') OR r1.ResaFin IS NULL /*OR r1.ResaFin IS NOT NULL*/ GROUP BY a.AppartId ORDER BY Debut, Fin
Et j'ai encore un soucis, lorsque les réservations ne sont pas dans ces critères
L'appartement correspondant n'est pas listé.Code:
1
2 AND (r1.ResaFin <= '2008-09-08' AND r1.ResaFin >='2008-08-28' AND r2.ResaDebut >= '2008-08-28')
par exemple si l'appartement est réservé jusqu'au au 08 août.
Pour ta requête, j'ai testé, de mon côté elle bug.
Merci comme même.
Bon effectivement, il manquait un alias (inutil sous oracle) et sous mysql le group by doit être avant le having, mais bon t'aurais pu chercher un peu,je t'avais dit que je maîtrisais pas trop la syntaxe mysql...Citation:
Pour ta requête, j'ai testé, de mon côté elle bug.
Donc voilà la requête qui bug plus :
et voici un jeu de test :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 SELECT app.AppartId FROM appartement as app WHERE NOT EXISTS ( SELECT 1 FROM ( SELECT sel.AppartId,min(sel.d1) AS deb, max(sel.d4) AS fin FROM ( SELECT a.AppartId, a.ResaDebut AS d1, a.ResaFin AS d2, b.ResaDebut AS d3, b.ResaFin AS d4 FROM reservation as a INNER JOIN reservation as b ON (a.AppartId=b.AppartId AND b.ResaDebut BETWEEN a.ResaFin AND a.ResaFin+1) ) as sel GROUP BY sel.AppartId HAVING min(sel.d1)<=curdate() AND max(sel.d4) >= curdate()+30 ) as pas_dispo WHERE pas_dispo.AppartId=app.AppartId )
Code:
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 mysql> select * from appartement; +----------+ | AppartId | +----------+ | 1 | | 2 | +----------+ 2 rows in set (0.00 sec) mysql> select * from reservation; +----------+----------+------------+------------+ | reservid | AppartId | ResaDebut | ResaFin | +----------+----------+------------+------------+ | 1 | 1 | 2008-08-15 | 2008-08-30 | | 2 | 1 | 2008-08-31 | 2008-09-15 | | 3 | 1 | 2008-09-16 | 2008-10-05 | | 4 | 2 | 2008-02-20 | 2008-03-15 | +----------+----------+------------+------------+ 4 rows in set (0.00 sec) mysql> SELECT app.AppartId -> FROM appartement as app -> WHERE NOT EXISTS ( -> SELECT 1 FROM ( -> SELECT sel.AppartId,min(sel.d1) AS deb, max(sel.d4) AS fin -> FROM ( -> SELECT a.AppartId, -> a.ResaDebut AS d1, -> a.ResaFin AS d2, -> b.ResaDebut AS d3, -> b.ResaFin AS d4 -> FROM reservation as a -> INNER JOIN reservation as b -> ON (a.AppartId=b.AppartId -> AND b.ResaDebut BETWEEN a.ResaFin AND a.ResaFin+1) -> ) as sel -> GROUP BY sel.AppartId -> HAVING min(sel.d1)<=curdate() AND max(sel.d4) >= curdate()+30 -> ) as pas_dispo -> WHERE pas_dispo.AppartId=app.AppartId -> ); +----------+ | AppartId | +----------+ | 2 | +----------+ 1 row in set (0.02 sec) mysql> update reservation set ResaDebut=date('2008-09-20') where reservid=3; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from reservation; +----------+----------+------------+------------+ | reservid | AppartId | ResaDebut | ResaFin | +----------+----------+------------+------------+ | 1 | 1 | 2008-08-15 | 2008-08-30 | | 2 | 1 | 2008-08-31 | 2008-09-15 | | 3 | 1 | 2008-09-20 | 2008-10-05 | | 4 | 2 | 2008-02-20 | 2008-03-15 | +----------+----------+------------+------------+ 4 rows in set (0.00 sec) mysql> SELECT app.AppartId -> FROM appartement as app -> WHERE NOT EXISTS ( -> SELECT 1 FROM ( -> SELECT sel.AppartId,min(sel.d1) AS deb, max(sel.d4) AS fin -> FROM ( -> SELECT a.AppartId,a.ResaDebut AS d1,a.ResaFin AS d2, b.ResaDebut AS d3, b.ResaFin AS d4 -> FROM reservation as a -> INNER JOIN reservation as b -> ON (a.AppartId=b.AppartId -> AND b.ResaDebut BETWEEN a.ResaFin AND a.ResaFin+1) -> ) as sel -> GROUP BY sel.AppartId -> HAVING min(sel.d1)<=curdate() AND max(sel.d4) >= curdate()+30 -> ) as pas_dispo -> WHERE pas_dispo.AppartId=app.AppartId -> ); +----------+ | AppartId | +----------+ | 1 | | 2 | +----------+ 2 rows in set (0.00 sec)
Par contre, je te garantis pas qu'elle traite tous les cas particuliers, mais au moins elle bug plus ;).
Mettez cela sous forme SQL CREATE + INSERT !
Comment voulez-vous que l'on puisse reproduire cehz nous votre problème !!!
A +