SELECT - CLAUSE WINDOW (Transact-SQL)

S’applique à : SQL Server 2022 (16.x)base de données Azure SQL Azure SQL Managed Instance

La définition de fenêtre nommée dans la WINDOW clause détermine le partitionnement et l’ordre d’un ensemble de lignes avant la fonction de fenêtre, qui utilise la fenêtre dans une OVER clause.

La WINDOW clause nécessite un niveau 160 de compatibilité de base de données ou supérieur. Si votre niveau de compatibilité de base de données est inférieur 160à , le Moteur de base de données ne peut pas exécuter de requêtes avec la WINDOW clause.

Vous pouvez vérifier le niveau de compatibilité dans la vue ou dans les sys.databases propriétés de base de données. Vous pouvez changer le niveau de compatibilité d’une base de données à l’aide de la commande suivante :

ALTER DATABASE DatabaseName
SET COMPATIBILITY_LEVEL = 160;

Conventions de la syntaxe Transact-SQL

Syntaxe

WINDOW window_name AS (
       [ reference_window_name ]
       [ <PARTITION BY clause> ]
       [ <ORDER BY clause> ]
       [ <ROW or RANGE clause> ]
      )

<PARTITION BY clause> ::=
PARTITION BY value_expression , ... [ n ]

<ORDER BY clause> ::=
ORDER BY order_by_expression
    [ COLLATE collation_name ]
    [ ASC | DESC ]
    [ , ...n ]

<ROW or RANGE clause> ::=
{ ROWS | RANGE } <window frame extent>

Arguments

window_name

Nom de la spécification de fenêtre définie. Ce nom est utilisé par les fonctions de fenêtre dans la OVER clause pour faire référence à la spécification de la fenêtre. Les noms de fenêtre doivent suivre les règles applicables aux identificateurs.

reference_window_name

Nom de la fenêtre référencée par la fenêtre active. La fenêtre référencée doit figurer parmi les fenêtres définies dans la WINDOW clause.

Les autres arguments sont :

  • PARTITION BY qui divise le jeu de résultats de la requête en partitions.

  • ORDER BY qui définit l’ordre logique des lignes dans chaque partition du jeu de résultats.

  • ROWS/RANGE qui limite davantage les lignes dans la partition en spécifiant les points de départ et de terminaison dans la partition.

Pour plus d’informations sur les arguments, consultez la clause OVER

Notes

Plusieurs fenêtres nommées peuvent être définies dans la WINDOW clause.

D’autres composants peuvent être ajoutés à une fenêtre nommée dans la OVER clause à l’aide de la window_name suivie des spécifications supplémentaires. Toutefois, les propriétés spécifiées dans WINDOW la clause ne peuvent pas être redéfinies dans la OVER clause.

Lorsqu’une requête utilise plusieurs fenêtres, une fenêtre nommée peut référencer une autre fenêtre nommée à l’aide de la window_name. Dans ce cas, la window_name référencée doit être spécifiée dans la définition de fenêtre de la fenêtre de référencement. Un composant de fenêtre défini dans une fenêtre ne peut pas être redéfini par une autre fenêtre qui le référence.

En fonction de l’ordre dans lequel les fenêtres sont définies dans la clause WINDOW, les références de fenêtre avant et arrière sont autorisées. En d’autres termes, une fenêtre peut utiliser n’importe quelle autre fenêtre définie dans l’expression de fenêtre dont elle fait partie, comme reference_window_name, quel que soit l’ordre dans lequel elles sont définies. Les références cycliques et l’utilisation de plusieurs références de fenêtre dans une seule fenêtre ne sont pas autorisées.

L’étendue de la nouvelle window_name d’une fenêtre définie contenue dans une expression de fenêtre se compose de toutes les définitions de fenêtre qui font partie de l’expression de fenêtre, ainsi que la SELECT clause de la spécification ou SELECT de l’instruction de requête qui contient la clause de fenêtre. Si l’expression de fenêtre est contenue dans une spécification de requête qui fait partie de l’expression de requête, qui est une requête de table de base, l’étendue du nouveau window_name inclut également l’expression ORDER BY , le cas échéant, de cette expression de requête.

Les restrictions relatives à l’utilisation des spécifications de fenêtre dans la OVER clause avec les fonctions d’agrégation et d’analyse en fonction de leur sémantique s’appliquent à WINDOW la clause.

Exemples

Les exemples de code Transact-SQL de cet article sont fondés sur l’échantillon de base de données AdventureWorks2022 ou AdventureWorksDW2022 fourni, que vous pouvez télécharger à partir de la page d’accueil Échantillons et projets communautaires Microsoft SQL Server.

R : Spécifier une fenêtre définie dans la clause de fenêtre

L’exemple de requête suivant montre comment utiliser une fenêtre nommée dans la OVER clause.

ALTER DATABASE AdventureWorks2022
SET COMPATIBILITY_LEVEL = 160;
GO

USE AdventureWorks2022;
GO

SELECT ROW_NUMBER() OVER win AS [Row Number],
    p.LastName,
    s.SalesYTD,
    a.PostalCode
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p
    ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
    ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
    AND SalesYTD <> 0
WINDOW win AS
    (
        PARTITION BY PostalCode ORDER BY SalesYTD DESC
    )
ORDER BY PostalCode;
GO

La requête suivante est l’équivalent de la requête précédente sans utiliser la WINDOW clause.

USE AdventureWorks2022;
GO

SELECT ROW_NUMBER() OVER (
        PARTITION BY PostalCode ORDER BY SalesYTD DESC
        ) AS [Row Number],
    p.LastName,
    s.SalesYTD,
    a.PostalCode
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p
    ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
    ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
    AND SalesYTD <> 0
ORDER BY PostalCode;
GO

Voici le jeu de résultats.

Row Number LastName SalesYTD PostalCode
1 Mitchell 4251368,5497 98027
2 Blythe 3763178,1787 98027
3 Carson 3189418,3662 98027
4 Reiter 2315185,611 98027
5 Vargas 1453719,4653 98027
6 Ansman-Wolfe 1352577,1325 98027
1 Pak 4116871,2277 98055
2 Varkey Chudukatil 3121616,3202 98055
3 Saraiva 2604540,7172 98055
4 Ito 2458535,6169 98055
5 Valdez 1827066,7118 98055
6 Mensa-Annan 1576562,1966 98055
7 Campbell 1573012,9383 98055
8 Tsoflias 1421810,9242 98055

B. Spécifier une seule fenêtre dans plusieurs clauses OVER

L’exemple suivant montre comment définir une spécification de fenêtre et l’utiliser plusieurs fois dans une OVER clause.

ALTER DATABASE AdventureWorks2022
SET COMPATIBILITY_LEVEL = 160;
GO

USE AdventureWorks2022;
GO

SELECT SalesOrderID,
    ProductID,
    OrderQty,
    SUM(OrderQty) OVER win AS [Total],
    AVG(OrderQty) OVER win AS [Avg],
    COUNT(OrderQty) OVER win AS [Count],
    MIN(OrderQty) OVER win AS [Min],
    MAX(OrderQty) OVER win AS [Max]
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN (43659, 43664)
WINDOW win AS (PARTITION BY SalesOrderID);
GO

La requête suivante est l’équivalent de la requête précédente sans utiliser la WINDOW clause.

USE AdventureWorks2022;
GO

SELECT SalesOrderID,
    ProductID,
    OrderQty,
    SUM(OrderQty) OVER (PARTITION BY SalesOrderID) AS [Total],
    AVG(OrderQty) OVER (PARTITION BY SalesOrderID) AS [Avg],
    COUNT(OrderQty) OVER (PARTITION BY SalesOrderID) AS [Count],
    MIN(OrderQty) OVER (PARTITION BY SalesOrderID) AS [Min],
    MAX(OrderQty) OVER (PARTITION BY SalesOrderID) AS [Max]
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN (43659, 43664);
GO

Voici le jeu de résultats.

SalesOrderID IDProduit OrderQty Total Avg Count Min Max
43659 776 1 26 2 12 1 6
43659 777 3 26 2 12 1 6
43659 778 1 26 2 12 1 6
43659 771 1 26 2 12 1 6
43659 772 1 26 2 12 1 6
43659 773 2 26 2 12 1 6
43659 774 1 26 2 12 1 6
43659 714 3 26 2 12 1 6
43659 716 1 26 2 12 1 6
43659 709 6 26 2 12 1 6
43659 712 2 26 2 12 1 6
43659 711 4 26 2 12 1 6
43664 772 1 14 1 8 1 4
43664 775 4 14 1 8 1 4
43664 714 1 14 1 8 1 4
43664 716 1 14 1 8 1 4
43664 777 2 14 1 8 1 4
43664 771 3 14 1 8 1 4
43664 773 1 14 1 8 1 4
43664 778 1 14 1 8 1 4

C. Définir une spécification commune dans la clause de fenêtre

Cet exemple montre comment définir une spécification commune dans une fenêtre et l’utiliser pour définir des spécifications supplémentaires dans la OVER clause.

ALTER DATABASE AdventureWorks2022
SET COMPATIBILITY_LEVEL = 160;
GO

USE AdventureWorks2022;
GO

SELECT SalesOrderID AS OrderNumber,
    ProductID,
    OrderQty AS Qty,
    SUM(OrderQty) OVER win AS Total,
    AVG(OrderQty) OVER (win PARTITION BY SalesOrderID) AS Avg,
    COUNT(OrderQty) OVER (
        win ROWS BETWEEN UNBOUNDED PRECEDING
            AND 1 FOLLOWING
        ) AS Count
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN (43659, 43664)
    AND ProductID LIKE '71%'
WINDOW win AS
    (
        ORDER BY SalesOrderID, ProductID
    );
GO

La requête suivante est l’équivalent de la requête précédente sans utiliser la WINDOW clause.

USE AdventureWorks2022;
GO

SELECT SalesOrderID AS OrderNumber,
    ProductID,
    OrderQty AS Qty,
    SUM(OrderQty) OVER (ORDER BY SalesOrderID, ProductID) AS Total,
    AVG(OrderQty) OVER (
        PARTITION BY SalesOrderID ORDER BY SalesOrderID, ProductID
        ) AS Avg,
    COUNT(OrderQty) OVER (
        ORDER BY SalesOrderID,
            ProductID ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING
        ) AS Count
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN (43659, 43664)
    AND ProductID LIKE '71%';
GO

Voici le jeu de résultats.

OrderNumber IDProduit Qté Total Avg Count
43659 711 4 4 4 2
43659 712 2 6 3 3
43659 714 3 9 3 4
43659 716 1 10 2 5
43664 714 1 11 1 6
43664 716 1 12 1 6

D. Références de fenêtre avant et arrière

Cet exemple montre l’utilisation de fenêtres nommées comme références avant et arrière lors de la définition d’une nouvelle fenêtre dans la WINDOW clause.

ALTER DATABASE AdventureWorks2022
SET COMPATIBILITY_LEVEL = 160;
GO

USE AdventureWorks2022;
GO

SELECT SalesOrderID AS OrderNumber, ProductID,
    OrderQty AS Qty,
    SUM(OrderQty) OVER win2 AS Total,
    AVG(OrderQty) OVER win1 AS Avg
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664) AND
    ProductID LIKE '71%'
WINDOW win1 AS (win3),
    win2 AS (ORDER BY SalesOrderID, ProductID),
    win3 AS (win2 PARTITION BY SalesOrderID);
GO

La requête suivante est l’équivalent de la requête précédente sans utiliser la WINDOW clause.

USE AdventureWorks2022;
GO

SELECT SalesOrderID AS OrderNumber, ProductID,
    OrderQty AS Qty,
    SUM(OrderQty) OVER (ORDER BY SalesOrderID, ProductID) AS Total,
    AVG(OrderQty) OVER (PARTITION BY SalesOrderID ORDER BY SalesOrderID, ProductID) AS Avg
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664) AND
    ProductID LIKE '71%';
GO

Voici le jeu de résultats.

OrderNumber IDProduit Qté Total Avg
43659 711 4 4 4
43659 712 2 6 3
43659 714 3 9 3
43659 716 1 10 2
43664 714 1 11 1
43664 716 1 12 1