У меня есть запрос, я продолжаю работать, и я хочу увеличить одно из полей и перезапустить счетчик, когда значение ключа отличается.
Я знаю, что этот код не работает. Программно это - то, что я хочу...
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
... с выглядящим примерно так конечным результатом:
ID Counter
3 1
3 2
3 3
3 4
6 1
6 2
6 3
7 1
И да, я застреваю с SQL2k. Иначе это row_number () работало бы.
Предполагая таблицу:
CREATE TABLE [SomeTable] (
[id] INTEGER,
[order] INTEGER,
PRIMARY KEY ([id], [order])
);
Один из способов получить это в Microsoft SQL Server 2000 - использовать подзапрос для подсчета строк с одинаковым id и более низким порядком.
SELECT *, (SELECT COUNT(*) FROM [SomeTable] counter
WHERE t.id = counter.id AND t.order < counter.order) AS row_num
FROM [SomeTable] t
Совет: На дворе 2010 год. Скоро ваш SQL Server будет достаточно стар, чтобы водить машину.
Если вы используете SQL Server 2005 или более позднюю версию, вы получите новые замечательные функции, такие как ROW_NUMBER() OVER (PARTITION...)
Да, вам нужен ROW_NUMBER().
Я бы попробовал:
SELECT id, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) AS Counter
Наличие row_number () означает, что вам придется иметь дело с гораздо меньшим количеством коррелированных подзапросов. Решение @Bill Karwin работает (+1); вот еще одна версия, которая делает то же самое, но которой будет немного легче следовать. (Я использовал дату и время для определения порядка.)
-- 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
Важно отметить, что без хороших индексов (и, возможно, даже с ними) такие запросы могут работать очень плохо, особенно с большими таблицами. Внимательно проверяйте и оптимизируйте!
Один из способов сделать это - бросить данные в временную таблицу с идентификационным столбцом, который используется в качестве номера строки. Затем сделать столбец counter подсчетом других строк с тем же Id и меньшим номером строки + 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;
Вы должны получить следующий результат, основанный на вашем примере:
Id Counter
3 1
3 2
3 3
3 4
6 1
6 2
6 3
7 1