web-dev-qa-db-ja.com

選択クエリでインクリメントする方法

作業中のクエリがあり、キー値が異なる場合は、フィールドの1つを増やしてカウンターを再起動します。

私はこのコードが機能しないことを知っています。プログラム的にこれは私が欲しいものです...

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()は機能します。

10
Mikecancook

テーブルを想定:

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

Microsoft SQL Server 2000でこれを取得する1つの方法は、サブクエリを使用して、同じ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...)のような素晴らしい新しい関数が得られます。

13
Bill Karwin

はい、ROW_NUMBER()が必要です。

私はしようとします:

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

これを行う1つの方法は、行番号として使用されるID列を含む一時テーブルにデータをスローすることです。次に、カウンター列を、同じ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
3
Jamie

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

これらの種類のクエリは、特に大きなテーブルでは、適切なインデックスがないと(おそらくインデックスがあっても)非常にうまく機能しない可能性があることに注意することが重要です。慎重に確認して最適化してください!

0
Philip Kelley

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