2010-07-09 2 views
9

Ho una query su cui sto lavorando e voglio incrementare uno dei campi e riavviare il contatore quando un valore chiave è diverso.Come incrementare in una query selezionata

So che questo codice non funziona. Programmazione questo è quello che voglio ...

declare @counter int, @id 
set @counter = 0 
set @id = 0 

select distinct 
    id, 
    counter = when id = @id 
       then @counter += 1 
      else @id = id 
       @counter = 1  

... con il risultato finale cercando qualcosa di simile:

ID Counter 
3  1 
3  2 
3  3 
3  4 
6  1 
6  2 
6  3 
7  1 

E sì, mi sono bloccato con SQL2K. Altrimenti che row_number() funzionerebbe.

+0

A seconda della resto di ciò che è disponibile nella tua query, forse il Row_Number() sarebbe d'aiuto? – reallyJim

+0

@reallyJim: se utilizzano SQL2K, come suggerito dai tag, "ROW_NUMBER" non sarà disponibile. – LukeH

+0

@LukeH TOTALMENTE ha mancato quel punto! – reallyJim

risposta

12

Assumendo una tabella:

CREATE TABLE [SomeTable] (
    [id] INTEGER, 
    [order] INTEGER, 
    PRIMARY KEY ([id], [order]) 
); 

Un modo per ottenere questo in Microsoft SQL Server 2000 è quello di utilizzare una sottoquery per contare le righe con lo stesso ID e un ordine inferiore.

SELECT *, (SELECT COUNT(*) FROM [SomeTable] counter 
      WHERE t.id = counter.id AND t.order < counter.order) AS row_num 
FROM [SomeTable] t 

Suggerimento: E 'il 2010. Presto il vostro SQL Server sarà l'età per guidare.

Se si utilizza SQL Server 2005 o versione successiva, si ottengono meravigliose nuove funzioni come ROW_NUMBER() OVER (PARTITION...).

+5

SQL 2000 è ancora divertente. A 13 anni, SQL Server 7.0 è scontroso per la maggior parte del tempo e gioca ai videogiochi tutto il giorno. –

+4

Attualmente stiamo lavorando alla prima auto di SQL2k. Se mantiene il naso pulito e ottiene buoni voti, sarà il suo regalo di compleanno di 16 anni. ; o) – Mikecancook

+3

Crescono così in fretta! * sniff * –

6

Sì, si desidera ROW_NUMBER().

Vorrei provare:

SELECT id, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) AS Counter 
+0

Impossibile: SQL Server non supportava funzioni analitiche/di posizionamento/finestre fino a v2005 –

1

Avere row_number() significa che devi gestire un numero molto inferiore di sottoquery correlate. La soluzione di @Bill Karwin funziona (+1); ecco un'altra versione che fa la stessa cosa ma potrebbe essere un po 'più facile da seguire. (Io ho usato datetimes per determinare l'ordine.)

-- Test table 
CREATE TABLE Test 
(Id  int  not null 
    ,Loaded datetime not null 
) 

-- Load dummy data with made-up distinct datetimes 
INSERT Test values (3, 'Jan 1, 2010') 
INSERT Test values (3, 'Jan 2, 2010') 
INSERT Test values (3, 'Jan 5, 2010') 
INSERT Test values (3, 'Jan 7, 2010') 
INSERT Test values (6, 'Feb 1, 2010') 
INSERT Test values (6, 'Feb 11, 2010') 
INSERT Test values (7, 'Mar 31, 2010') 


-- The query 
SELECT t1.Id, count(*) Counter 
from Test t1 
    inner join Test t2 
    on t2.Id = t1.Id 
    and t2.Loaded <= t1.Loaded 
group by t1.Id, t1.Loaded 


-- Clean up when done 
DROP TABLE Test 

E 'importante notare che, senza buoni indici (e forse anche con loro), questi tipi di query possono eseguire molto male, in particolare su tabelle di grandi dimensioni. Controlla e ottimizza attentamente!

3

Un modo per eseguire questa operazione consiste nel trasferire i dati in una tabella temporanea con una colonna Identity utilizzata come numero di riga. Poi fare la colonna contatore un conteggio delle altre righe con lo stesso ID e un numero di riga inferiore + 1.

CREATE TABLE #MyData(
Id INT 
); 

INSERT INTO #MyData VALUES(3); 
INSERT INTO #MyData VALUES(3); 
INSERT INTO #MyData VALUES(3); 
INSERT INTO #MyData VALUES(3); 
INSERT INTO #MyData VALUES(6); 
INSERT INTO #MyData VALUES(6); 
INSERT INTO #MyData VALUES(6); 
INSERT INTO #MyData VALUES(7); 

CREATE TABLE #MyTempTable(
RowNum INT IDENTITY(1,1), 
Id INT, 
Counter INT 
); 

INSERT INTO #MyTempTable 
SELECT Id, 0 
FROM #MyData 
ORDER BY Id; 

SELECT Id, (SELECT COUNT(*) + 1 FROM #MyTempTable WHERE Id = t1.Id AND RowNum < t1.RowNum) AS 'Counter' 
FROM #MyTempTable t1; 

si dovrebbe ottenere il seguente output sulla base di tuo esempio:

Id Counter 
3 1 
3 2 
3 3 
3 4 
6 1 
6 2 
6 3 
7 1