19 May 2009

Numerare le righe con SQL Server 2005

Questo metodo è ancora più rapido di quello precedente (vedi sotto), perché prescinde dall'ordinamento dei campi (il trucco è usare la clausola ORDER BY GETDATE()

DECLARE @tab1 AS TABLE
(
    id int PRIMARY KEY
  , name nvarchar(20)
)


INSERT @tab1 (id, name)
      SELECT 100, 'Marty McFly'
UNION SELECT 200, 'Emmett Brown'
UNION SELECT 300, 'Biff Tannen'


SELECT *
FROM @tab1


SELECT   *
  , row_id = ROW_NUMBER() OVER (ORDER BY GETDATE())
FROM    @tab1


SELECT   *
  , row_id = ROW_NUMBER() OVER (ORDER BY GETDATE())
FROM    @tab1
WHERE id >= 200

Output:
id          name
----------- --------------------
100         Marty McFly
200         Emmett Brown
300         Biff Tannen


id          name                 row_id
----------- -------------------- --------------------
100         Marty McFly          1
200         Emmett Brown         2
300         Biff Tannen          3


id          name                 row_id
----------- -------------------- --------------------
200         Emmett Brown         1
300         Biff Tannen          2


Sintassi di ROW_NUMBER()

Trovato qui.



Illustriamo come è possibile eseguire la stessa operazione in SQL Server 2005 sfruttando la nuova funzione ROW_NUMBER().
La funzione ROW_NUMBER() restituisce il numero sequenziale di una riga in una partizione di un result set, partendo da 1 per la prima riga di ogni partizione. La clausola OVER(), obbligatoria, determina la partizione e l'ordinamento del rowset prima che la funzione associata venga applicata.
Vediamo un paio di esempi:
USE tempdb;
GO

/* Definisco la tabella dbo.myTable */
CREATE TABLE dbo.myTable(
Codice varchar(6) NOT NULL,
Descrizione varchar(25) NOT NULL
);
GO

/* La popolo */
SET NOCOUNT ON;
INSERT dbo.myTable VALUES('SQL2K', 'SQL Server 2000');
INSERT dbo.myTable VALUES('SQL2K5', 'SQL Server 2005');
INSERT dbo.myTable VALUES('VB6', 'Visual Basic 6');
INSERT dbo.myTable VALUES('VB2K5', 'Visual Basic 2005');
INSERT dbo.myTable VALUES('VB2K5E', 'Visual Basic 2005 Express');
SET NOCOUNT OFF;
GO

/* Query */
SELECT
Codice
, Descrizione
, ROW_NUMBER() OVER(ORDER BY Codice) AS 'Row Number'
FROM dbo.myTable;
GO

/* Output:

Codice Descrizione Row Number
------ ------------------------- --------------------
SQL2K SQL Server 2000 1
SQL2K5 SQL Server 2005 2
VB2K5 Visual Basic 2005 3
VB2K5E Visual Basic 2005 Express 4
VB6 Visual Basic 6 5

(5 row(s) affected)

*/

/* Pulizia */
DROP TABLE dbo.myTable;
Questa volta definisco una partizione sulla colonna Codice:
/* Definisco la tabella dbo.myTable */
CREATE TABLE dbo.myTable(
Codice varchar(6) NOT NULL,
Descrizione varchar(25) NOT NULL
);
GO

/* La popolo */
SET NOCOUNT ON;
INSERT dbo.myTable VALUES('SQL', 'SQL Server 2000');
INSERT dbo.myTable VALUES('SQL', 'SQL Server 2005');
INSERT dbo.myTable VALUES('VB', 'Visual Basic 6');
INSERT dbo.myTable VALUES('VB', 'Visual Basic 2005');
INSERT dbo.myTable VALUES('VB', 'Visual Basic 2005 Express');
SET NOCOUNT OFF;
GO

/* Query */
SELECT
Codice
, Descrizione
, ROW_NUMBER() OVER(PARTITION BY Codice ORDER BY Codice) AS 'Row Number'
FROM dbo.myTable;
GO

/* Output:

Codice Descrizione Row Number
------ ------------------------- --------------------
SQL SQL Server 2000 1
SQL SQL Server 2005 2
VB Visual Basic 6 1
VB Visual Basic 2005 2
VB Visual Basic 2005 Express 3

(5 row(s) affected)

*/

/* Pulizia */
DROP TABLE dbo.myTable;