Как увеличить в запросе выбора - PullRequest
10 голосов
/ 09 июля 2010

У меня есть запрос, над которым я работаю, и я хочу увеличить одно из полей и перезапустить счетчик, если значение ключа отличается

Я знаю, что этот код не работает. Программно это то, что я хочу ...

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 () будет работать.

Ответы [ 5 ]

13 голосов
/ 09 июля 2010

Принимая таблицу:

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

Одним из способов получить это в Microsoft SQL Server 2000 является использование подзапроса для подсчета строк с одинаковым идентификатором и более низким порядком.

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...).

6 голосов
/ 09 июля 2010

Да, вы хотите ROW_NUMBER ().

Я бы попробовал:

SELECT id, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) AS Counter
3 голосов
/ 09 июля 2010

Один из способов сделать это - выбросить данные во временную таблицу со столбцом идентификаторов, который используется в качестве номера строки. Затем сделайте в столбце счетчика количество других строк с таким же идентификатором и меньшим номером строки + 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
0 голосов
/ 03 января 2019

Для MySql мне удалось сделать это с помощью этого запроса.

SELECT (SELECT COUNT(id) +1 FROM sku s WHERE t.item_id = s.item AND s.id < t.sku_id) AS rowNumber, t.*
FROM
(select item.Name as itemName ,item.id as item_id , sku.Name as skuName ,sku.id as sku_id from item
    INNER JOIN sku ON item.id = sku.item
    WHERE item.active = 'Y' 
) t


1   Roasted Pistachios (Salted, In Shell)   84  1 Pound Bags    84
3   Roasted Pistachios (Salted, In Shell)   84  25 Pound Cases  1174
5   Roasted Pistachios (Salted, In Shell)   84  12 x 2.6 Ounce Bags 5807
2   Roasted Pistachios (Salted, In Shell)   84  5 Pound Bags    814
4   Roasted Pistachios (Salted, In Shell)   84  Samples 4724
6   Roasted Pistachios (Salted, In Shell)   84  12 x 3.2 Ounce Bags 18145
4   Star Fruit  981 5 Pound Bags    17462
1   Star Fruit  981 1 Pound Bags    2125
3   Star Fruit  981 11 Pound Bags   2226
2   Star Fruit  981 44 Pound Cases  2156
0 голосов
/ 09 июля 2010

Наличие row_number () означает, что вам приходится иметь дело с гораздо меньшим количеством коррелированных подзапросов.Решение @Bill Karwin работает (+1);Вот еще одна версия, которая делает то же самое, но это может быть немного легче следовать.(Я использовал datetime для определения порядка.)

--  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

Важно отметить, что без хороших индексов (и, возможно, даже с ними) такие запросы могут работать очень плохо, особенно в больших таблицах.Тщательно проверяйте и оптимизируйте!

...