Dela via


SELECT – WINDOW-sats (Transact-SQL)

Gäller för: SQL Server 2022 (16.x) och senare versioner Azure SQL DatabaseAzure SQL Managed InstanceSQL Database i Förhandsversion av Microsoft Fabric

Den namngivna fönsterdefinitionen WINDOW i -satsen bestämmer partitionering och ordning för en raduppsättning före fönsterfunktionen, som använder fönstret i en OVER sats.

Satsen WINDOW kräver databaskompatibilitetsnivå 160 eller högre. Om databasens kompatibilitetsnivå är lägre än 160kan databasmotorn inte köra frågor med WINDOW -satsen.

Du kan kontrollera kompatibilitetsnivån i sys.databases vyn eller i databasegenskaperna. Du kan ändra kompatibilitetsnivån för en databas med följande kommando:

ALTER DATABASE DatabaseName
SET COMPATIBILITY_LEVEL = 160;

Transact-SQL syntaxkonventioner

Syntax

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

Namnet på den definierade fönsterspecifikationen. Det här namnet används av fönsterfunktionerna OVER i -satsen för att referera till fönsterspecifikationen. Fönsternamn måste följa reglerna för identifierare.

reference_window_name

Namnet på fönstret som refereras av det aktuella fönstret. Det refererade fönstret måste finnas bland de fönster som definierats i WINDOW -satsen.

De andra argumenten är:

  • PARTITION BY som delar frågeresultatuppsättningen i partitioner.

  • ORDER BY som definierar den logiska ordningen för raderna i varje partition i resultatuppsättningen.

  • RADER/INTERVALL som begränsar raderna i partitionen genom att ange start- och slutpunkter i partitionen.

Mer specifik information om argumenten finns i OVER-satsen

Remarks

Mer än ett namngivet WINDOW fönster kan definieras i -satsen.

Fler komponenter kan läggas till i ett namngivet OVER fönster i -satsen med hjälp av window_name följt av de extra specifikationerna. Egenskaperna som anges i WINDOW -satsen kan dock inte omdefinieras i OVER -satsen.

När en fråga använder flera fönster kan ett namngivet fönster referera till ett annat namngivet fönster med hjälp av window_name. I det här fallet måste den refererade window_name anges i fönsterdefinitionen för referensfönstret. En fönsterkomponent som definieras i ett fönster kan inte definieras om av ett annat fönster som refererar till den.

Baserat på i vilken ordning fönstren definieras i fönstersatsen tillåts referenser för framåt- och bakåtfönster. Med andra ord kan ett fönster använda andra fönster som definierats i det fönsteruttryck som det är en del av, som reference_window_name, oavsett i vilken ordning de definieras. Cykliska referenser och användning av flera fönsterreferenser i ett enda fönster tillåts inte.

Omfånget för den nya window_name för ett definierat fönster som finns i ett fönsteruttryck består av alla fönsterdefinitioner som ingår i fönsteruttrycket, tillsammans med SELECT satsen i frågespecifikationen eller SELECT -instruktionen som innehåller fönstersatsen. Om fönsteruttrycket finns i en frågespecifikation som är en del av frågeuttrycket, som är en grundläggande tabellfråga, innehåller omfånget för den nya ORDER BY även uttrycket, om någon, för frågeuttrycket.

Begränsningarna för användning av fönsterspecifikationer i OVER -satsen med aggregerade och analytiska funktioner baserat på deras semantik gäller för WINDOW -satsen.

Examples

Kodexemplen i den här artikeln använder AdventureWorks2022- eller AdventureWorksDW2022-exempeldatabasen, som du kan ladda ned från startsidan Microsoft SQL Server Samples och Community Projects.

A. Ange ett fönster som definierats i fönstersatsen

Följande exempelfråga visar använder ett namngivet OVER fönster i -satsen.

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

Följande fråga motsvarar den tidigare frågan utan att använda WINDOW -satsen.

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

Här är resultatet.

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. Ange ett enda fönster i flera OVER-satser

I följande exempel visas hur du definierar en fönsterspecifikation och använder den flera gånger i en OVER sats.

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

Följande fråga motsvarar den tidigare frågan utan att använda WINDOW -satsen.

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

Här är resultatet.

SalesOrderID ProductID 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. Definiera gemensam specifikation i window-sats

Det här exemplet visar hur du definierar en gemensam specifikation i ett fönster och använder den för att definiera ytterligare specifikationer i OVER -satsen.

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

Följande fråga motsvarar den tidigare frågan utan att använda WINDOW -satsen.

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

Här är resultatet.

OrderNumber ProductID Qty 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. Referenser för framåt- och bakåtfönster

Det här exemplet visar hur du använder namngivna fönster som framåt- och bakåtreferenser när du definierar ett nytt fönster i WINDOW -satsen.

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

Följande fråga motsvarar den tidigare frågan utan att använda WINDOW -satsen.

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

Här är resultatet.

OrderNumber ProductID Qty 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