web-dev-qa-db-fra.com

Comment incrémenter dans une requête de sélection

Je travaille sur une requête et je souhaite incrémenter l'un des champs et redémarrer le compteur lorsqu'une valeur de clé est différente. 

Je sais que ce code ne fonctionne pas. Par programme c'est ce que je veux ...

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     

... avec le résultat final qui ressemble à ceci:

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

Et oui, je suis coincé avec SQL2k. Sinon, row_number () fonctionnerait.

10
Mikecancook

En supposant une table:

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

Une façon d'obtenir cela dans Microsoft SQL Server 2000 consiste à utiliser une sous-requête pour compter les lignes avec le même identifiant et un ordre inférieur.

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

Astuce: Nous sommes en 2010. Votre serveur SQL sera bientôt assez vieux pour conduire. 

Si vous utilisez SQL Server 2005 ou une version ultérieure, vous obtiendrez de merveilleuses nouvelles fonctions telles que ROW_NUMBER() OVER (PARTITION...).

13
Bill Karwin

Oui, vous voulez ROW_NUMBER ().

Je voudrais essayer: 

SELECT id, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) AS Counter
6
Eddie

Pour ce faire, vous pouvez notamment jeter les données dans une table temporaire avec une colonne d'identité utilisée comme numéro de ligne. Ensuite, faites de la colonne de compteur un compte des autres lignes avec le même Id et un numéro de ligne inférieur + 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;

Vous devriez obtenir le résultat suivant basé sur votre exemple:

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

Si row_number () signifie que vous devez traiter beaucoup moins de sous-requêtes corrélées. La solution de @Bill Karwin fonctionne (+1); voici une autre version qui fait la même chose mais qui pourrait être un peu plus facile à suivre. (J'ai utilisé datetime pour déterminer l'ordre.)

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

Il est important de noter que, sans de bons index (et peut-être même avec eux), ces types de requêtes peuvent très mal fonctionner, en particulier sur les grandes tables. Vérifiez et optimisez soigneusement!

0
Philip Kelley

Pour MySQL, j'ai pu le faire avec cette requête.

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