Bonjour,
Dans le cadre d'une optimisation, je cherche à réduire le nombre de requêtes SQL faites lors du chargement d'une page. J'ai actuellement les quatre requêtes suivantes qui sont faites :
Dans chacune de ses requêtes, nous ne voulons en fait que le premier résultat pour l'affichage dans un tableau (BI et surveillance des données). Mettre un TOP 1 est facilement envisageable, mais cela ne change pas le fait qu'il faille réduire le nombre de requêtes. La première étape est donc la concaténation de ces 4 requêtes en une seule. Après de nombreuses recherches sur mon problème, j'en suis arrivé à ce type de requête :
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 SELECT P.[Starting Date] as current_promo FROM [Sales Price] P WHERE P.[Item No_] = :id AND P.[Ending Date] >= getdate() AND P.[Starting Date] <= getdate() ORDER BY P.[Starting Date] ASC; SELECT P.[Starting Date] as current_promo FROM [Purchase Line Discount] P WHERE P.[Item No_] = :id AND (P.[Line Discount_] > 0 OR P.[Line Discount_2] > 0) AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000') AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000') ORDER BY P.[Starting Date] ASC; SELECT P.[Lot Quantity] as lot, P.[Free Quantity] as free FROM [Purchase Price] P WHERE P.[Item No_] = :id AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000') AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000') ORDER BY P.[Ending Date] ASC; SELECT P.[Starting Date] as next_promo FROM [Purchase Price] P WHERE P.[Item No_] = :id AND P.[Minimum Quantity] = 1 AND P.[Ending Date] > P.[Starting Date] AND P.[Starting Date] > getdate() ORDER BY P.[Starting Date] ASC;
Lorsque je lance la requête directement sur la base de données, j'ai les bons résultats attendus, c'est-à-dire une unique ligne avec un résultat ou null s'il n'y a pas de résultat. La seconde étape, mettre un BATCH pour avoir plusieurs IDs, est donc triviale.
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 SELECT sales_promo, purchase_promo, lot, free, next_promo FROM ( SELECT TOP 1 P.[Starting Date] as sales_promo FROM [Purchase Line Discount] P WHERE P.[Item No_] = :id AND (P.[Line Discount _] > 0 OR P.[Line Discount _ 2] > 0) AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000') AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000') ORDER BY P.[Starting Date] ASC ) salesPromo FULL OUTER JOIN ( SELECT TOP 1 P.[Starting Date] as purchase_promo FROM [Purchase Line Discount] P WHERE P.[Item No_] = :id AND (P.[Line Discount _] > 0 OR P.[Line Discount _ 2] > 0) AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000') AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000') ORDER BY P.[Starting Date] ASC ) purchasePromo ON 1=1 FULL OUTER JOIN ( SELECT TOP 1 P.[Lot Quantity] as lot, P.[Free Quantity] as free FROM [Purchase Price] P WHERE P.[Item No_] = :id AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000') AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000') ORDER BY P.[Ending Date] ASC ) lotandfee ON 1=1 FULL OUTER JOIN ( SELECT TOP 1 P.[Starting Date] as next_promo FROM [Purchase Price] P WHERE P.[Item No_] = :id AND P.[Minimum Quantity] = 1 AND P.[Ending Date] > P.[Starting Date] AND P.[Starting Date] > getdate() ORDER BY P.[Starting Date] ASC ) nextPromo ON 1=1
Le problème :
En faisant cette requête avec PDO, puisque sur beaucoup de sous-requêtes je n'ai pas de résultat, il n'y a plus de lignes du tout. Par exemple, sur la seconde sous-requête, j'ai toujours un résultat. Mais si je n'en ai pas sur les trois autres, je n'ai aucune ligne en sortie. Alors qu'en exécutant la requête directement sur la base, j'ai mon résultat correct.
Ci-dessous une autre requête qui me donne le même résultat :
J'ai cherché un peu partout d'où pourrait venir le problème. Je pense que c'est PDO qui enlève automatiquement les sous-requêtes avec NULL... Mais je suis un peu perdu, j'ai l'habitude de MySQL et c'est la première fois que je bosse sur MSSQL.
Si quelqu'un a une piste, je suis preneur !
Partager