5

次のようなテーブルにいくつかのデータがあります。

アイテム 日付 価格
A 2012 年 8 月 29 日 $3
B 2012 年 8 月 29 日 $23
C 2012 年 8 月 29 日 $10
A 2012 年 8 月 30 日 $4
B 2012 年 8 月 30 日 $25
C 2012 年 8 月 30 日 $11
A 2012 年 8 月 31 日 $3
B 2012 年 8 月 31 日 $22
C 2012 年 8 月 31 日 $8
A 2012 年 9 月 1 日 $3
B 2012 年 9 月 1 日 $26
C 2012 年 9 月 1 日 $9
A 2012 年 9 月 2 日 $3
B 2012 年 9 月 2 日 $24
C 2012 年 9 月 2 日 $9

A の価格が 2012 年 8 月 30 日以降変更されていないこと、アイテム C の価格が 2012 年 9 月 1 日以降変更されていないこと、および両方の経過日数を返すクエリを作成する必要があります (価格が変動しないアイテムを探しています)。このSQLを実行する必要があるWebレポートツールの制限のため、CTE、カーソル、または個別に作成された一時テーブル(select intoなど)を使用できません。「基本的な」シングルパス選択クエリのみを使用できます(ただし、サブクエリは機能します)。これを達成する方法について狡猾なアイデアを持っている人はいますか??

私の最初の試みは、価格が最新の価格と同じであるアイテムと価格でグループ化しhaving count > 2、最小日付を識別し、最小日付と getdate の間で datediff を実行することでした。ただし、これはその価格の最初のインスタンスを識別するだけで、価格が異なる可能性のある後続の行は考慮されません。それが理にかなっていることを願っています。

4

3 に答える 3

2

私は、最も適切な場所で Windows 機能を使用することを好みます。そして、この場合、一連の同じものを見つけるための興味深いトリックがあります。アイテムごとに分割され、日付順に並べられたすべてのデータに対してそれらを (row_number で) 列挙します。次に、アイテムと価格で分割され、日付順に並べられたすべてのデータを列挙します。

A の場合、次のようになります。

A 8/29 $3 1 1
A 8/30 $4 2 1
A 8/31 $3 3 2
A 9/1  $3 4 3
A 9/3  $3 5 4

最後の 2 つの列の差は一定で、データ内で価格が一定のままです。これを使用して、そのシーケンスがいつ始まるかを見つけることができます。次のクエリは、このアプローチを採用しています。

select item, price, (id_seqnum - ipd_seqnum) as groupid, min(date) as mindate
from (select p.*,
             row_number() over (partition by item order by date) id_seqnum,
             row_number() over (partition by item, price order by date) as ipd_seqnum,
             max(date) over (partition by item) as maxdate
      from prices p
     ) t
group by item, price, (id_seqnum - ipd_seqnum)
having max(date) = max(maxdate)

また、各アイテムの最大日付を見つけて、最大日付を持つグループを選択します。

于 2012-09-24T20:15:40.547 に答える
2

*フィドルで更新: *

これは機能しますか?

SELECT ct.Item,
    ct.Price,
    datediff(day, max(yt.[Date]), ct.[Date]) AS ChangeDays
FROM
    (SELECT Item, max(Date) as LastDate FROM YourTable GROUP BY Item) maxdata
    INNER JOIN YourTable ct on ct.Item = maxdata.Item and ct.[Date] = maxdata.LastDate
    INNER JOIN YourTable yt on yt.Item = ct.Item and yt.[Date] < ct.[Date] and yt.Price <> ct.Price
GROUP BY ct.Item, ct.Price, ct.[Date]
于 2012-09-24T19:52:14.960 に答える
2

両方のタイプの年齢を指定し、テーブルに 1 回だけ存在するアイテムを説明しました (古い日付はありません)。これがどれほど近いか教えてください。

更新: 「PriceAgeToNow」の日付計算を修正する必要がありました。また、新しい価格が 1 日しかないレコードを除外しようとしました。これがSQL Fiddleです。

-- Get the age of the current price
select *
    , datediff(d, c.OldDate, getdate()) as PriceAgeToNow
    , datediff(d, c.OldDate, c.NewDate) as PriceAgeToNewestDate
from (
    select *
        -- Get max date of former price
        , isnull(
            (select max(Date) from PricingTable where Item = b.Item and Date < b.NewDate and Price != b.NewPrice), b.NewDate
        ) as OldDate
    from (
        -- Get current price
        select *
            , (select Price from PricingTable where Item = a.Item and Date = a.NewDate) as NewPrice
        from (
            -- Get current date
            select Item
                , max(Date) as NewDate
            from PricingTable
            group by Item
        ) a
    ) b
) c
-- Attempt to filter out price changes that have only lasted 1 day
where datediff(d, c.OldDate, c.NewDate) > 1
于 2012-09-24T19:52:39.703 に答える