1

特定のアイテムが特定の場所にいつ発送または返送されたかを記録するテーブルがあり、特定のアイテムが返送されるたびに間隔を計算したいと考えています。

サンプルデータ:

Item   ReturnDate:
Item1, 20120101
Item1, 20120201
Item1, 20120301
Item2, 20120401
Item2, 20120601

したがって、この場合、アイテム 1 が最初に返品されるまでに 1 か月のギャップがあり、2 回目に返品されるまでにさらに 1 か月のギャップがあったことがわかります。アイテム2は2か月後に戻ってきました。

私の出発点は次のとおりです。

Select r1.Item, r1.ReturnDate, r2.Item, r2.ReturnDate, DateDiff(m, r1.ReturnDate, r2.ReturnDate)
from Returns r1
inner join Returns r2 on r2.VehicleNo = r1.VehicleNo

ただし、このサンプルでは、​​各項目は、次の項目だけでなく、それが返された他のすべてのインスタンスと比較されます。したがって、隣接するリターンのみを比較するように、このクエリを制限する必要があります。

1 つの解決策は、各返品にカウント (アイテムが返品された回数) をタグ付けすることです。

Item   ReturnDate, ReturnNo:
Item1, 20120101,   1
Item1, 20120201,   2
Item1, 20120301,   3
Item2, 20120401,   1
Item2, 20120601,   2

これにより、次の T-SQL (または同様のもの) を使用できるようになります。

Select r1.Item, r1.ReturnDate, r2.Item, r2.ReturnDate, DateDiff(m, r1.ReturnDate, r2.ReturnDate)
from Returns r1
inner join Returns r2 on r2.VehicleNo = r1.VehicleNo 
and (r1.ReturnNo + 1 = r2.ReturnNo)

私の最初の質問は、これが賢明で最適なアプローチなのか、それともより良いアプローチがあるのか​​ということです。

次に、ReturnNo を計算する最も簡単で巧妙な方法は何ですか?

4

3 に答える 3

4

SQL Server 2005 以降を使用している場合は、ROW_NUMBER() を使用して、必要なことを正確に実行します。

WITH RankedReturn AS
(
  SELECT Item, ReturnDate, 
    ROW_NUMBER() OVER (PARTITION BY Item ORDER BY ReturnDate DESC) AS ReturnNo
  FROM Returns
)
SELECT * FROM RankedReturn

明らかに、CTE を取得したので、必要なものを外側の SELECT に入れることができます。これには OUTER APPLY を使用します。

WITH RankedReturn AS
(
  SELECT Item, ReturnDate, 
    ROW_NUMBER() OVER (PARTITION BY Item ORDER BY ReturnDate DESC) AS ReturnNo
  FROM Returns
)
SELECT rOuter.Item, rOuter.ReturnDate, DATEDIFF(month, prev.PrevDate, ReturnDate) AS Months
FROM RankedReturn rOuter
OUTER APPLY 
  (
    SELECT ReturnDate AS PrevDate 
    FROM RankedReturn rInner 
    WHERE rOuter.Item = rInner.Item AND rOuter.ReturnNo = rInner.ReturnNo - 1
  ) prev

おっと、SQL Fiddle はこちらです。

月差計算が逆だったので修正。現在修正済み

于 2012-06-12T14:35:39.107 に答える
3

ReturnNo を計算する最も簡単な方法は、次を使用することOVERです。

SELECT [Item], [ReturnDate], 
    ROW_NUMBER() OVER (PARTITION BY [Item] ORDER BY [ReturnDate]) AS ReturnNumber
FROM Returns

http://sqlfiddle.com/#!3/e18ad/1/0

また、現在の合計を計算して 2 つの行の差を 計算する手法を利用することもできます。

于 2012-06-12T14:35:22.617 に答える
2

これは私がそれを行う方法です:

select  itemNo,
        dt,
        DATEDIFF(day, previousDt, dt) as daysSince
from    (select itemNo, 
                dt,
                (select top 1 dt from testTable where itemNo = outerTbl.itemNo and dt < outerTbl.dt order by dt desc) as previousDt
        from    testTable as outerTbl
        ) as x

...そして、これに対する解決策をテストする他の人のためのセットアップコードを少し示します

create table testTable(
itemNo nvarchar(20),
dt datetime)
go

insert into testTable values('Item1', '2012-01-01');
insert into testTable values('Item1', '2012-02-01');
insert into testTable values('Item1', '2012-03-01');
insert into testTable values('Item2', '2012-04-01');
insert into testTable values('Item2', '2012-05-01');
go
于 2012-06-12T14:38:15.910 に答える