Condividi tramite


TOP (Transact-SQL)

Limita le righe restituite nel set di risultati di una query a un numero specificato o a una percentuale di righe in SQL Server 2012. Se la clausola TOP viene usata insieme alla clausola ORDER BY, il set di risultati è limitato al primo numero N di righe ordinate. In caso contrario, viene restituito il primo numero N di righe in ordine casuale. Usare questa clausola per specificare il numero di righe restituite da un'istruzione SELECT o interessate da un'istruzione INSERT, UPDATE, MERGE o DELETE. 

Icona di collegamento a un argomento Convenzioni della sintassi Transact-SQL

Sintassi

[ 
    TOP (expression) [PERCENT]
    [ WITH TIES ]
]

Argomenti

  • expression
    Espressione numerica che specifica il numero di righe da restituire. Se viene specificato PERCENT, expression viene convertito in modo implicito in un valore float. In caso contrario, viene convertito in un valore bigint.

  • PERCENT
    Indica che la query restituisce solo la prima percentuale di righe dal set di risultati specificata in expression. I valori frazionari vengono arrotondati al valore intero più vicino.

  • WITH TIES
    Utilizzato quando si desidera restituire due o più righe che hanno un valore equivalente per l'ultima posizione nel set di risultati limitato. Deve essere usato con la clausola ORDER BY. WITH TIES può comportare la restituzione di un numero maggiore di righe rispetto al valore specificato in expression. Ad esempio, se expression è impostato su 5, ma 2 righe aggiuntive corrispondono ai valori delle colonne ORDER BY nella riga 5, nel set di risultati saranno contenute 7 righe.

    È possibile specificare TOP...WITH TIES solo nelle istruzioni SELECT e solo se viene specificata una clausola ORDER BY. L'ordine restituito per l'associazione dei record è arbitrario. ORDER BY non riguarda questa regola.

Procedure consigliate

In un'istruzione SELECT utilizzare sempre una clausola ORDER BY con la clausola TOP. È l'unico modo per indicare prevedibilmente quali righe sono interessate dalla clausola TOP.

Utilizzare OFFSET e FETCH nella clausola ORDER BY anziché la clausola TOP per implementare una soluzione di paging delle query. Una soluzione di paging, ovvero l'invio di blocchi o "pagine" di dati al client, è di più facile implementazione con le clausole OFFSET e FETCH. Per ulteriori informazioni, vedere Clausola ORDER BY (Transact-SQL).

Utilizzare TOP (o OFFSET e FETCH) anziché SET ROWCOUNT per limitare il numero di righe restituite. Questi metodi vengono preferiti all'utilizzo di SET ROWCOUNT per i motivi seguenti:

  • Come parte di un'istruzione SELECT, in Query Optimizer il valore di expression nella clausola TOP o FETCH può essere preso in considerazione durante l'ottimizzazione della query. Poiché SET ROWCOUNT viene utilizzato al di fuori di un'istruzione che esegue una query, il relativo valore non può essere utilizzato in un piano di query.

Supporto della compatibilità

Per garantire la compatibilità con le versioni precedenti, le parentesi sono facoltative nelle istruzioni SELECT. È consigliabile utilizzare sempre le parentesi per le clausole TOP nelle istruzioni SELECT per coerenza con le istruzioni INSERT, UPDATE, MERGE e DELETE in cui le parentesi sono obbligatorie.

Interoperabilità

L'espressione TOP non influisce sulle istruzioni eventualmente eseguite a causa dell'attivazione di un trigger. Le tabelle inserted e deleted nei trigger restituiranno solo le righe effettivamente interessate dalle istruzioni INSERT, UPDATE, MERGE o DELETE. Se ad esempio INSERT TRIGGER viene attivato come risultato di un'istruzione INSERT che ha utilizzato una clausola TOP,

SQL Server consente l'aggiornamento delle righe attraverso le viste. Poiché la clausola TOP può essere inclusa nella definizione della vista, è possibile che alcune righe scompaiano dalla vista in seguito a un aggiornamento se le righe non soddisfano più i requisiti dell'espressione TOP.

Se specificata nell'istruzione MERGE, la clausola TOP viene applicata dopo l'unione in join dell'intera tabella di origine e dell'intera tabella di destinazione e dopo la rimozione delle righe unite in join non qualificate per un'azione di inserimento, aggiornamento o eliminazione. La clausola TOP riduce ulteriormente il numero di righe unite in join in base al valore specificato e l'azione di inserimento, aggiornamento o eliminazione viene applicata alle righe unite in join rimanenti in modo non ordinato. Questo significa che le righe vengono distribuite tra le azioni definite nelle clausole WHEN senza alcun ordine. Si supponga ad esempio che l'utilizzo della clausola TOP (10) interessi 10 righe. Di queste righe, 7 possono essere aggiornate e 3 inserite oppure 1 riga può essere eliminata, 5 aggiornate e 4 inserite e così via. Poiché l'istruzione MERGE esegue un'analisi completa di entrambe le tabelle di origine e di destinazione, l'utilizzo della clausola TOP per modificare una tabella di grandi dimensioni creando più batch può influire sulle prestazioni di I/O. In questo scenario è importante assicurare che tutti i batch successivi vengano destinati a nuove righe.

Prestare attenzione quando si specifica la clausola TOP in una query che contiene un operatore UNION, UNION ALL, EXCEPT o INTERSECT. È possibile scrivere una query che restituisce risultati imprevisti perché l'ordine in cui le clausole TOP e ORDER BY vengono elaborate logicamente non è sempre intuitivo quando questi operatori vengono utilizzati in un'operazione di selezione. Ad esempio, considerati i dati e la tabella seguenti, si supponga di voler ottenere come risultato la macchina rossa meno costosa e la macchina blu più costosa, ovvero la berlina rossa e il furgone blu.

CREATE TABLE dbo.Cars(Model varchar(15), Price money, Color varchar(10));
INSERT dbo.Cars VALUES
    ('sedan', 10000, 'red'), ('convertible', 15000, 'blue'), 
    ('coupe', 20000, 'red'), ('van', 8000, 'blue');

Per ottenere questi risultati, è possibile scrivere la query seguente.

SELECT TOP(1) Model, Color, Price
FROM dbo.Cars
WHERE Color = 'red'
UNION ALL
SELECT TOP(1) Model, Color, Price
FROM dbo.Cars
WHERE Color = 'blue'
ORDER BY Price ASC;

Set di risultati:

Model         Color      Price

------------- ---------- -------

sedan         red        10000.00

convertible   blue       15000.00

I risultati imprevisti vengono restituiti perché la clausola TOP viene eseguita logicamente prima della clausola ORDER BY che consente di ordinare i risultati dell'operatore (UNION ALL in questo caso). La query precedente restituisce pertanto qualsiasi macchina rossa e qualsiasi macchina blu, quindi ordina il risultato di quell'unione in base al prezzo. Nell'esempio seguente viene illustrato il metodo corretto per scrivere questa query per ottenere il risultato desiderato.

SELECT Model, Color, Price
FROM (SELECT TOP(1) Model, Color, Price
      FROM dbo.Cars
      WHERE Color = 'red'
      ORDER BY Price ASC) AS a
UNION ALL
SELECT Model, Color, Price
FROM (SELECT TOP(1) Model, Color, Price
      FROM dbo.Cars
      WHERE Color = 'blue'
      ORDER BY Price ASC) AS b;

Tramite le clausole TOP e ORDER BY in un'operazione sub-SELECT, ci si assicura che i risultati della clausola ORDER BY vengano utilizzati applicati alla clausola TOP e non all'ordinamento del risultato dell'operazione UNION.

Set di risultati:

Model         Color      Price

------------- ---------- -------

sedan         red        10000.00

van           blue        8000.00

Limitazioni e restrizioni

Se la clausola TOP viene utilizzata con INSERT, MERGE o DELETE, le righe a cui viene fatto riferimento non vengono disposte in alcun ordine e la clausola ORDER BY non può essere specificata direttamente in tali istruzioni. Se è necessario utilizzare TOP per inserire, eliminare o modificare righe in un ordine cronologico significativo, è necessario utilizzare TOP con una clausola ORDER BY specificata in un'istruzione sub-SELECT. Vedere la sezione Esempi più avanti in questo argomento.

Non è possibile utilizzare TOP nelle istruzioni UPDATE e DELETE in viste partizionate.

Non è possibile combinare TOP con OFFSET e FETCH nella stessa espressione di query (nello stesso ambito della query). Per ulteriori informazioni, vedere Clausola ORDER BY (Transact-SQL).

Esempi

Categoria

Elementi di sintassi inclusi

Sintassi di base

TOP • PERCENT

Inclusione di valori equivalenti

WITH TIES

Limitazione delle righe interessate da DELETE, INSERT o UPDATE

DELETE • INSERT • UPDATE

Sintassi di base

Negli esempi contenuti in questa sezione vengono illustrate le funzionalità di base della clausola ORDER BY utilizzando la sintassi minima necessaria.

A. Utilizzo di TOP con un valore costante

Negli esempi seguenti viene utilizzato un valore costante per specificare il numero di dipendenti restituiti nel set di risultati della query. Nel primo esempio le prime 10 righe non definite vengono restituite perché non viene utilizzata una clausola ORDER BY. Nel secondo esempio viene utilizzata una clausola ORDER BY per restituire i primi 10 dipendenti assunti di recente.

USE AdventureWorks2012;
GO
-- Select the first 10 random employees.
SELECT TOP(10)JobTitle, HireDate
FROM HumanResources.Employee;
GO
-- Select the first 10 employees hired most recently.
SELECT TOP(10)JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY HireDate DESC;

A. Utilizzo di TOP con una variabile

Nell'esempio seguente viene utilizzata una variabile per specificare il numero di dipendenti restituiti nel set di risultati della query.

USE AdventureWorks2012;
GO
DECLARE @p AS int = 10;
SELECT TOP(@p)JobTitle, HireDate, VacationHours
FROM HumanResources.Employee
ORDER BY VacationHours DESC
GO

C. Specifica di una percentuale

Nell'esempio seguente viene utilizzato PERCENT per specificare il numero di dipendenti restituiti nel set di risultati della query. Nella tabella HumanResources.Employee sono presenti 290 dipendenti. Poiché il 5 percento di 290 è un valore frazionario, il valore viene arrotondato al numero intero più vicino.

USE AdventureWorks2012;
GO
SELECT TOP(5)PERCENT JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY HireDate DESC;

Inclusione di valori equivalenti

A. Utilizzo di WITH TIES per includere righe corrispondenti ai valori nell'ultima riga

Nell'esempio seguente viene restituita la percentuale 10 di tutti i dipendenti che percepiscono lo stipendio più alto in ordine decrescente in base al salario. WITH TIES garantisce che nel set di risultati vengano inclusi anche tutti i dipendenti con uno stipendio pari allo stipendio più basso restituito (ultima riga), anche se in questo modo viene superata la percentuale di dipendenti 10.

USE AdventureWorks2012;
GO
SELECT TOP(10)WITH TIES
pp.FirstName, pp.LastName, e.JobTitle, e.Gender, r.Rate
FROM Person.Person AS pp 
    INNER JOIN HumanResources.Employee AS e
        ON pp.BusinessEntityID = e.BusinessEntityID
    INNER JOIN HumanResources.EmployeePayHistory AS r
        ON r.BusinessEntityID = e.BusinessEntityID
ORDER BY Rate DESC;

Limitazione delle righe interessate da DELETE, INSERT o UPDATE

A. Utilizzo di TOP per limitare il numero di righe eliminate

Quando si utilizza una clausola TOP (n) con l'istruzione DELETE, l'operazione di eliminazione viene eseguita su una selezione non definita di un numero n di righe. In altre parole, l'istruzione DELETE sceglie un numero (n) di righe qualsiasi che soddisfano i criteri definiti nella clausola WHERE. Nell'esempio seguente vengono eliminate 20 righe dalla tabella PurchaseOrderDetail con scadenze precedenti al 1* luglio 2002.

USE AdventureWorks2012;
GO
DELETE TOP (20) 
FROM Purchasing.PurchaseOrderDetail
WHERE DueDate < '20020701';
GO

Se si desidera utilizzare TOP per eliminare righe in un ordine cronologico significativo, è necessario utilizzare questa clausola insieme a ORDER BY in un'istruzione sub-SELECT. Tramite la query seguente vengono eliminate le 10 righe della tabella PurchaseOrderDetail contenenti le date di scadenza più imminenti. Per assicurarsi che vengano eliminate solo 10 righe, la colonna specificata nell'istruzione di selezione secondaria (PurchaseOrderID) è la chiave primaria della tabella. L'utilizzo di una colonna non chiave nell'istruzione sub-SELECT può avere come conseguenza l'eliminazione di più di 10 righe se la colonna specificata contiene valori duplicati.

USE AdventureWorks2012;
GO
DELETE FROM Purchasing.PurchaseOrderDetail
WHERE PurchaseOrderDetailID IN
   (SELECT TOP 10 PurchaseOrderDetailID 
    FROM Purchasing.PurchaseOrderDetail 
    ORDER BY DueDate ASC);
GO

B. Utilizzo di TOP per limitare il numero di righe inserite

Nell'esempio seguente viene creata la tabella EmployeeSales in cui vengono inseriti il nome e i dati di vendita da inizio anno per i primi 5 dipendenti dalla tabella HumanResources.Employee. L'istruzione INSERT sceglie 5 righe qualsiasi restituite dall'istruzione SELECT che soddisfano i criteri definiti nella clausola WHERE. La clausola OUTPUT consente di visualizzare le righe inserite nella tabella EmployeeSales. Si noti che la clausola ORDER BY nell'istruzione SELECT non viene utilizzata per determinare i primi 5 dipendenti.

USE AdventureWorks2012 ;
GO
IF OBJECT_ID ('dbo.EmployeeSales', 'U') IS NOT NULL
    DROP TABLE dbo.EmployeeSales;
GO
CREATE TABLE dbo.EmployeeSales
( EmployeeID   nvarchar(11) NOT NULL,
  LastName     nvarchar(20) NOT NULL,
  FirstName    nvarchar(20) NOT NULL,
  YearlySales  money NOT NULL
 );
GO
INSERT TOP(5)INTO dbo.EmployeeSales
    OUTPUT inserted.EmployeeID, inserted.FirstName, inserted.LastName, inserted.YearlySales
    SELECT sp.BusinessEntityID, c.LastName, c.FirstName, sp.SalesYTD 
    FROM Sales.SalesPerson AS sp
    INNER JOIN Person.Person AS c
        ON sp.BusinessEntityID = c.BusinessEntityID
    WHERE sp.SalesYTD > 250000.00
    ORDER BY sp.SalesYTD DESC;

Se è necessario utilizzare TOP per inserire righe in un ordine cronologico significativo, è necessario utilizzare questa clausola insieme a ORDER BY in un'istruzione sub-SELECT, come illustrato nell'esempio seguente. La clausola OUTPUT consente di visualizzare le righe inserite nella tabella EmployeeSales. I primi 5 dipendenti vengono ora inseriti in base ai risultati della clausola ORDER BY anziché alle righe non definite.

INSERT INTO dbo.EmployeeSales
    OUTPUT inserted.EmployeeID, inserted.FirstName, inserted.LastName, inserted.YearlySales
    SELECT TOP (5) sp.BusinessEntityID, c.LastName, c.FirstName, sp.SalesYTD 
    FROM Sales.SalesPerson AS sp
    INNER JOIN Person.Person AS c
        ON sp.BusinessEntityID = c.BusinessEntityID
    WHERE sp.SalesYTD > 250000.00
    ORDER BY sp.SalesYTD DESC;

C. Utilizzo di TOP per limitare il numero di righe aggiornate

Nell'esempio seguente viene utilizzata la clausola TOP per aggiornare righe in una tabella. Quando si utilizza una clausola TOP (n) con l'istruzione UPDATE, l'operazione di aggiornamento viene eseguita su un numero non definito di righe. In altre parole, l'istruzione UPDATE sceglie un numero (n) di righe qualsiasi che soddisfano i criteri definiti nella clausola WHERE. Nell'esempio seguente vengono assegnati 10 clienti da un venditore a un altro.

USE AdventureWorks2012;
UPDATE TOP (10) Sales.Store
SET SalesPersonID = 276
WHERE SalesPersonID = 275;
GO

Se è necessario utilizzare TOP per applicare gli aggiornamenti in un ordine cronologico significativo, è necessario utilizzare questa clausola insieme a ORDER BY in un'istruzione sub-SELECT. Nell'esempio seguente le ore di ferie dei 10 dipendenti vengono aggiornate con le prime date di assunzione.

UPDATE HumanResources.Employee
SET VacationHours = VacationHours + 8
FROM (SELECT TOP 10 BusinessEntityID FROM HumanResources.Employee
     ORDER BY HireDate ASC) AS th
WHERE HumanResources.Employee.BusinessEntityID = th.BusinessEntityID;
GO

Vedere anche

Riferimento

SELECT (Transact-SQL)

INSERT (Transact-SQL)

UPDATE (Transact-SQL)

DELETE (Transact-SQL)

Clausola ORDER BY (Transact-SQL)

SET ROWCOUNT (Transact-SQL)

MERGE (Transact-SQL)