2016-10-13 9 views
1

私は立ち往生しています。私は顧客注文データベースに入り、13か月以上の休止後に顧客が注文したことを毎月特定する必要があります。これは約3万人の顧客と7年間で約355,000件の注文になります。例えばカスタマーオーダー間のギャップを特定

...顧客#123は、次の数ヶ月で注文を言う:

CustomerNumber OrderMonth 
123    Jan 2010 
123    Feb 2010 
123    Apr 2010 
123    Jul 2011 
123    Jan 2013 
123    Feb 2013 
123    Aug 2015 

この例では、私は3行がそれらの各以来、顧客123のために、次の数ヶ月が含まれていることが返さ必要があるだろう注文がなかったところで少なくとも13ヶ月の間隙があった。

CustomerNumber OrderMonth 
123    Jul 2011 
123    Jan 2013 
123    Aug 2015 

私はSQL Server 2008 R2を使用しているため、ツールボックスではリード/ラグは利用できません。私は通常、実用的で効率的ではないにしても、ある種の解決法を発明することができます...しかし、これは私に困ってしまいます。任意のアイデアをいただければ幸いです!

+0

ordermonthのデータ型は何ですか?それは日付か文字列ですか? –

+0

ここから始めましょう。 http://spaghettidba.com/2015/04/24/how-to-post-at-sql-question-on-a-public-forum/ –

+0

[こちら](http://stackoverflow.com/questions)をご覧ください。/710212 /前に行の値を選択する文にアクセスする) – techspider

答えて

1

テーブル自体を結合する方法を解説しますが、各注文は以前の注文と一致します。そこにすべての列が表示されているわけではありませんが、OrderNumberというフィールドがあると想像してください(計算することができます)。次に、あなたはそのようなものを書くでしょう:

SELECT ... 
FROM Orders a JOIN Orders b ON a.CutomerId = b.CustomerId AND a.OrderNumber = b.OrderNumber + 1 
WHERE DateDiff(a.OrderDate, b.OrderDate, M) > 13 
+0

まだ試したことはありませんが、これはすべきことです....私の精神ブロックZdravkoを去ってくれてありがとう! –

0

いつもnot existsと書くことができます。あなたは(> 2012 SQL Server用)の違いを取得するために、鉛を使用することができます

select * 
    from your_order_table o 
where not exists(select 1 
        from your_order_table o2 
        where o.CustomerNumber = o2.CustomerNumber 
         and o2.orderDate >= dateadd(month,-13,o.orderDate) 
         and o2.orderDate < o.orderDate) 
+0

13ヶ月のギャップ条件を満たす多くの月の組み合わせがあります。しかし、私は、私が推測する前の行だけを見てください。 –

+0

がvkpに同意します。あなたの洞察と提案の両方に感謝します。 –

+0

@vkp - 「存在しない」と指定すると、過去13か月間に他の注文がない注文が返されます。最も最近の先行注文を明示的に見つける必要はない(データベースはこれを評価するために適切なインデックスがあると仮定しているが、そうするだろう)。 –

2
Declare @YourTable table (CustomerNumber int, OrderMonth Date) 
Insert Into @YourTable values 
(123,'2010-01-01'), 
(123,'2010-02-01'), 
(123,'2010-04-01'), 
(123,'2011-07-01'), 
(123,'2013-01-01'), 
(123,'2013-02-01'), 
(123,'2015-08-01') 

;with cteBase as (
    Select * 
      ,RowNr = Row_Number() over (Partition By CustomerNumber Order By OrderMonth) 
    From @YourTable 
) 
Select A.CustomerNumber 
     ,OrderMonth  = Left(DateName(MM,A.OrderMonth),3)+' '+cast(Year(A.OrderMonth) as varchar(4)) 
     ,NumberOfMonths = DateDiff(MM,B.OrderMonth,A.OrderMonth) 
    From cteBase A 
    Join cteBase B on (A.RowNr=B.RowNr+1) 
    Where DateDiff(MM,B.OrderMonth,A.OrderMonth)>=13 

戻り

CustomerNumber OrderMonth NumberOfMonths 
123    Jul 2011 15 
123    Jan 2013 18 
123    Aug 2015 30 
+0

ジョン、ありがとう、私はかなりこのZdravkoの以前の応答に基づいて正確なことをやりました。後で明白なようだが、私は完全な精神的な壁を持っていた。 –

+0

@JasonSmith私たちすべてに起こります。時にはあなたはちょっとした仕事をしているだけで、あなたに来ることもあります。よくやった。 –

0

;WITH cte 
AS (SELECT 
    *, LEAD(ordermonth, 1, ordermonth) OVER (PARTITION BY customerNumber ORDER BY ordermonth) AS nextordermonth 
FROM yourtable) 
SELECT CustomerNumber, nextordermonth 
FROM cte 
WHERE DATEDIFF(m, ordermonth, nextordermonth) > 13 

表構造

create table yourtable (CustomerNumber Int, OrderMonth date) 

Insert Into YourTable values 
(123,'2010-01-01'), 
(123,'2010-02-01'), 
(123,'2010-04-01'), 
(123,'2011-07-01'), 
(123,'2013-01-01'), 
(123,'2013-02-01'), 
(123,'2015-08-01') 
+0

私の最初の選択肢やアプローチはありますが、OPは2008年であり、リード/ラグは彼にとってはオプションではありません。 –

関連する問題