SELECT : cláusula WINDOW (Transact-SQL)

Se aplica a: SQL Server 2022 (16.x) Azure SQL Database Azure SQL Managed Instance

La definición de ventana con nombre de la WINDOW cláusula determina la creación de particiones y el orden de un conjunto de filas antes de la función de ventana, que usa la ventana en una OVER cláusula .

La WINDOW cláusula requiere un nivel 160 de compatibilidad de base de datos o superior. Si el nivel de compatibilidad de la base de datos es inferior a 160, el Motor de base de datos no puede ejecutar consultas con la WINDOW cláusula .

Puede comprobar el nivel de compatibilidad en la vista o en las propiedades de la sys.databases base de datos. Se puede cambiar el nivel de compatibilidad de una base de datos mediante el comando siguiente:

ALTER DATABASE DatabaseName
SET COMPATIBILITY_LEVEL = 160;

Convenciones de sintaxis de Transact-SQL

Sintaxis

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>

Argumentos

window_name

Nombre de la especificación de ventana definida. Las funciones de ventana usan este nombre en la OVER cláusula para hacer referencia a la especificación de la ventana. Los nombres de ventana deben cumplir las reglas de los identificadores.

reference_window_name

Nombre de la ventana a la que hace referencia la ventana actual. La ventana a la que se hace referencia debe estar entre las ventanas definidas en la WINDOW cláusula .

Los otros argumentos son:

  • PARTITION BY, que divide el conjunto de resultados de la consulta en particiones.

  • ORDER BY, que define el orden lógico de las filas dentro de cada partición del conjunto de resultados.

  • ROWS/RANGE, que limita aún más las filas de la partición especificando los puntos inicial y final.

Para obtener detalles más específicos sobre los argumentos, consulte la cláusula OVER.

Comentarios

Se puede definir más de una ventana con nombre en la WINDOW cláusula .

Se pueden agregar más componentes a una ventana con nombre en la OVER cláusula mediante el window_name seguido de las especificaciones adicionales. Sin embargo, las propiedades especificadas en WINDOW la cláusula no se pueden volver a definir en la OVER cláusula .

Cuando una consulta usa varias ventanas, una ventana con nombre puede hacer referencia a otra ventana con nombre mediante el window_name. En este caso, el window_name al que se hace referencia debe especificarse en la definición de ventana de la ventana de referencia. Un componente de ventana definido en una ventana no se puede volver a definir mediante otra ventana que haga referencia a ella.

Las referencias a una ventana anterior o posterior dependerán del orden en que las ventanas estén definidas en la cláusula WINDOW. En otras palabras, una ventana puede usar cualquier otra ventana definida en la expresión de ventana de la que forma parte, como reference_window_name, independientemente del orden en que se definan. No se permiten las referencias cíclicas ni el uso de varias referencias de ventana en una sola ventana.

El ámbito de la nueva window_name de una ventana definida contenida en una expresión de ventana, consta de cualquier definición de ventana que forme parte de la expresión de ventana, junto con la SELECT cláusula de la especificación o SELECT instrucción de consulta que contiene la cláusula window. Si la expresión de ventana está contenida en una especificación de consulta que forma parte de la expresión de consulta, que es una consulta de tabla básica, el ámbito del nuevo window_name también incluye la ORDER BY expresión, si existe, de esa expresión de consulta.

Las restricciones para el uso de especificaciones de ventana en la OVER cláusula con las funciones de agregado y análisis en función de su semántica son aplicables a la WINDOW cláusula .

Ejemplos

Los ejemplos de código de Transact-SQL de este artículo utilizan la base de datos de ejemplo AdventureWorks2022 o AdventureWorksDW2022, que se pueden descargar desde la página principal de Ejemplos y proyectos de la comunidad de Microsoft SQL Server.

A Especificar una ventana definida en la cláusula window

En la consulta de ejemplo siguiente se muestra cómo se usa una ventana con nombre en la OVER cláusula .

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 consulta siguiente es el equivalente de la consulta anterior sin usar la WINDOW cláusula .

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

Este es el conjunto de resultados.

Row Number Apellidos 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. Especificar una sola ventana en varias cláusulas OVER

En el ejemplo siguiente se muestra cómo definir una especificación de ventana y usarla varias veces en una OVER cláusula .

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 consulta siguiente es el equivalente de la consulta anterior sin usar la WINDOW cláusula .

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

Este es el conjunto de resultados.

Id.OrdenVentas ProductID OrderQty Total Avg Count Mín. Máx.
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. Definición de la especificación común en la cláusula window

En este ejemplo se muestra cómo definir una especificación común en una ventana y usarla para definir especificaciones adicionales en la OVER cláusula .

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 consulta siguiente es el equivalente de la consulta anterior sin usar la WINDOW cláusula .

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

Este es el conjunto de resultados.

OrderNumber ProductID Cant. 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. Referencias a ventanas anteriores y posteriores

En este ejemplo se muestra el uso de ventanas con nombre como referencias hacia delante y hacia atrás al definir una nueva ventana en la WINDOW cláusula .

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 consulta siguiente es el equivalente de la consulta anterior sin usar la WINDOW cláusula .

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

Este es el conjunto de resultados.

OrderNumber ProductID Cant. 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