1

SQL Server 2012 で次のものを作成したいと考えています (これを説明するには、テーブルを使用するのが最善の方法であることがわかりました)。

購入日、顧客ID、および顧客が支払った価格を次のような表に示します。

DateOnly     Customer    Price
2012/01/01      1         50
2012/01/01      2         60      
2012/01/01      3         80
2012/01/02      4         40
2012/01/02      5         30
2012/01/02      1         55
2012/01/03      6         80
2012/01/04      2         90

次に私がしなければならないことは、顧客が支払った平均価格を記録しておくことです。次のようになります。

DateOnly     Customer    Price    AveragePrice
2012/01/01      1         50           50
2012/01/01      2         60           60
2012/01/01      3         80           80
2012/01/02      4         40           40
2012/01/02      5         30           30
2012/01/02      1         55          52.5
2012/01/03      6         80           80 
2012/01/04      2         90           75

最後に、顧客が支払った平均価格が 10% を超えて上昇した行を選択する必要があります。

この場合、顧客 2 の 2 番目の注文のみを選択する必要があります。これは、この顧客が支払う平均価格が 10% より高くなったためです。

したがって、結果のテーブルは次のようになります。

DateOnly     Customer    Price    AveragePrice
2012/01/04      2         90           75

よろしくお願いします。

4

2 に答える 2

1

最初の CTE は、データを準備する = 行番号を各顧客の購入に割り当て、さらに結合で使用することです。

2 番目の CTE は再帰的であり、進行中のすべての作業を行います。最初の部分は、各顧客の最初の購入を取得することであり、再帰的な部分は次の購入時に結合し、TotalPrice、AveragePrice、および Increase を計算します。

最後に、増加率が 10% を超える行を選択します。

WITH CTE_Prep AS 
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY DateOnly) RN
    FROM Table1
)
,CTE_Calc AS
(
    SELECT *, Price AS TotalPrice, CAST(Price AS DECIMAL(18,2)) AS AveragePrice, CAST (0 AS DECIMAL(18,2)) AS Increase 
    FROM CTE_Prep WHERE RN = 1

    UNION ALL

    SELECT p.*
        , c.TotalPrice + p.Price AS TotalPrice 
        , CAST(CAST(c.TotalPrice + p.Price AS DECIMAL(18,2)) / p.RN AS DECIMAL(18,2)) AS AveragePrice
        , CAST(CAST(CAST(c.TotalPrice + p.Price AS DECIMAL(18,2)) / p.RN AS DECIMAL(18,2)) / c.AveragePrice AS DECIMAL(18,2)) AS Increase
    FROM CTE_Calc c
    INNER JOIN CTE_Prep p ON c.RN + 1 = p.RN  AND p.Customer = c.Customer
)
SELECT * FROM CTE_Calc
WHERE Increase > 1.10

SQLFiddle デモ

于 2013-07-29T14:55:55.423 に答える
1

興味深い問題です。

行のすべての価格の合計から各行の価格を差し引くことで、現在の購入なしで平均を取得できます。この観察は、ウィンドウ関数と組み合わせて、探している行を取得するために必要な情報を提供します。

select *
from (select t.*,
             avg(price) over (partition by customer) as avgprice,
             sum(price) over (partition by customer) as sumprice,
             count(price) over (partition by customer) as cntprice
      from table1 t
     ) t
where (case when cntprice > 1
            then (sumprice - price) / (cntprice - 1) 
       end) > avgprice*1.1;

caseでの使用に注意してください。whereゼロ除算の問題が発生する可能性があります。SQL Server は、ケースの部分が(シチュエーションの) 部分whenの前に評価されることを保証します。thenしたがって、これはその問題から安全です。

于 2013-07-29T14:40:18.820 に答える