Dans RAQL, SELECT aggregationFunction(x) OVER(ORDER BY y) FROM s est équivalent sur le plan sémantique à SELECT aggregationFunction (x) OVER(ORDER BY y ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM s. Toutefois, la norme SQL définit la sémantique afin qu'elle corresponde à SELECT aggregationFunction (x) OVER(ORDER BY y RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM s, ce qui signifie que la ligne actuelle, mais également toutes les lignes 'appariés' (lignes identiques à la ligne actuelle en ce qui concerne leur ordre) sont contenues dans la fenêtre. Autrement dit, un agrégat continu sans spécification explicite du cadre de fenêtre produit à l'heure actuelle des résultats différents dans RAQL et dans tout SGBD compatible avec la norme SQL.
Pour garantir un haut niveau de compatibilité avec la norme SQL, les cadres des fenêtres peuvent également définis avec le mot-clé RANGE.
Sémantique
Les cadres des fenêtres définis avec le mot-clé ROWS sont faciles à comprendre. La clause du cadre de fenêtre ROWS BETWEEN x PRECEDING AND y FOLLOWING définit simplement deux décalages x et y, qui déterminent pour chaque ligne dans la partition d'entrée le premier et le dernier numéros des lignes de la fenêtre correspondante par rapport au numéro de ligne actuel. PRECEDING et FOLLOWINGindiquent seulement si le décalage est négatif (le numéro de ligne précède le numéro de ligne actuel) ou positif.
Table 2. Exemple
rowNumber |
ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING |
ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING |
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING |
1 |
Window = [1,4] |
Window = [] |
Window = [1,10] |
2 |
Window = [1,5] |
Window = [1,1] |
Window = [2,10] |
3 |
Window = [1,6] |
Window = [1,2] |
Window = [3,10] |
4 |
Window = [1,7] (du numéro de ligne 4-3 à 4+3) |
Window = [1,3] |
Window = [4,10] |
5 |
Window = [2,8] |
Window = [2,4] |
Window = [5,10] |
6 |
Window = [3,9] |
Window = [3,5] |
Window = [6,10] |
7 |
Window = [4,10] |
Window = [4,6] |
Window = [7,10] |
8 |
Window = [5,10] |
Window = [5,7] |
Window = [8,10] |
9 |
Window = [6,10] |
Window = [6,8] |
Window = [9,10] |
10 |
Window = [7,10] |
Window = [7,9] |
Window = [10,10] |
D'un autre côté, la sémantique des spécifications des cadres de fenêtres utilisant le mot-clé RANGE ne dépend pas des numéros physiques des lignes, mais des valeurs réelles d'une colonne. Pourtant, la clause du cadre de fenêtre définit deux décalages x et y, mais ces décalages ne sont pas ajoutés au numéro de ligne, mais à une valeur de colonne réelle. De ce fait, toute spécification de cadre de fenêtre impliquant RANGE et un décalage différent de UNBOUNDED PRECEDING, UNBOUNDED FOLLOWING ou CURRENT ROW exige que la fenêtre soit disposée sur une seule colonne et que cette colonne contienne des données de type numérique (afin de permettre le calcul arithmétique du décalage).
Table 3. Exemple
rowNumber |
salary |
SELECT avg(salary) OVER (ORDER BY salary RANGE BETWEEN 300 PRECEDING AND 300 FOLLOWING) FROM ... |
fenêtre considérée |
|
1 |
1750 |
1850 |
[1450,2050] |
salaires compris entre 1750 - 300 et 1750 + 300 |
2 |
1900 |
1850 |
[1600,2200] |
|
3 |
1900 |
1850 |
[1600,2200] |
|
4 |
2200 |
2100 |
[1900,2500] |
|
5 |
2400 |
2300 |
[2100,2700] |
|
6 |
2750 |
2866,67 |
[2450,3050] |
|
7 |
2900 |
2980 |
[2600,3200] |
|
8 |
2950 |
2980 |
[2650,3250] |
|
9 |
3100 |
2980 |
[2800,3400] |
|
10 |
3200 |
2980 |
[2900,3500] |
Table 4. Exemple
rowNumber |
salary |
SELECT avg(salary) OVER (ORDER BY salary RANGE BETWEEN 300 PRECEDING AND 300 FOLLOWING) FROM ... |
fenêtre considérée |
|
1 |
1750 |
1 |
[1750,1750] |
salaires compris entre 1750 - 0 et 1750 + 0 |
2 |
1900 |
2 |
[1900,1900] |
|
3 |
1900 |
2 |
[1900,1900] |
|
4 |
2200 |
1 |
[2200,2100] |
|
5 |
2400 |
1 |
[2400,2400] |
|
6 |
2750 |
1 |
[2750,2750] |
|
7 |
2900 |
1 |
[2900,2900] |
|
8 |
2950 |
1 |
[2950,2950] |
|
9 |
3100 |
1 |
[3100,3100] |
|
10 |
3200 |
1 |
[3200,3200] |
Remarque : Les décalages dans une clause de cadre RANGE définissent des décalages logiques dans la séquence ordonnée définie par la clause order by. Si la clause order by précise un ordre décroissant (voir l'exemple suivant), le décalage 10 PRECEDING se traduit par "une valeur qui précède la valeur actuelle dans la séquence actuelle et qui diffère au plus de 10 (années/unités/...) »
Table 5. Exemple
rowNumber |
age |
SELECT COUNT(*) OVER (ORDER BY age DESC RANGE 10 PRECEDING) FROM ... |
fenêtre considérée |
|
1 |
75 |
1 |
[85, 75] |
âges compris entre 75 + 10 et 75 - 0 |
2 |
68 |
2 |
[78, 68] |
|
3 |
68 |
2 |
[72, 62] |
|
4 |
56 |
2 |
[66, 56] |
|
5 |
55 |
3 |
[65, 55] |
|
6 |
51 |
3 |
[61, 51] |
|
7 |
48 |
5 |
[58, 48] |
|
8 |
48 |
5 |
[58, 48] |
|
9 |
47 |
6 |
[57, 47] |
|
10 |
43 |
5 |
[53, 43] |
Requêtes impactées
Comme mentionné précédemment, le nouveau spécificateur RANGE a été introduit pour assurer la compatibilité avec la norme SQL. Il n'existe cependant que très peu de cas où des requêtes existantes risquent d'être impactées par ces changements. Seules les requêtes définissant une fonction de fenêtre avec
une spécification explicite order by et
AUCUNE spécification explicite de cadre de fenêtre risquent d'être impactées si
les expressions définies dans la clause order by ne sont pas uniques pour chaque ligne.
Si les expressions order by sont uniques, si chaque ligne n'a aucune ligne appariée en ce qui concerne l'ordre et si la clause du cadre de fenêtre ajouté implicitement RANGE UNBOUNDED PRECEDING est équivalente à ROWS UNBOUNDED PRECEDING, les résultats de la requête sont alors les mêmes qu'auparavant. Toutefois, si la spécification order by n'est pas unique, certaines lignes risquent d'avoir une ou plusieurs lignes appariées, si bien que les résultats de la requête sont différents du résultat fourni par les versions RAQL précédentes et l'utilisateur pourrait souhaiter ajouter explicitement une clause de cadre de fenêtre ROWS UNBOUNDED PRECEDING pour produire les résultats antérieurs.