5

我的表中有一些类似于此的数据:

项目 日期 价格
2012 年 8 月 29 日 3 美元
B 2012 年 8 月 29 日 23 美元
C 2012 年 8 月 29 日 10 美元
2012 年 8 月 30 日 4 美元
B 2012 年 8 月 30 日 25 美元
C 2012 年 8 月 30 日 11 美元
2012 年 8 月 31 日 3 美元
B 2012 年 8 月 31 日 22 美元
C 2012 年 8 月 31 日 8 美元
2012 年 9 月 1 日 3 美元
B 2012 年 9 月 1 日 26 美元
C 2012 年 9 月 1 日 9 美元
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、游标或单独创建的临时表(选择进入等)。我只能使用“基本”单通道选择查询(子查询将起作用)。有没有人对如何实现这一目标有任何狡猾的想法?

我的第一次尝试是按项目和价格分组,其中价格与最新价格相同having count > 2,确定最小日期并在最小日期和 getdate 之间进行 datediff。然而,这只是识别该价格的第一个实例,它没有考虑任何可能具有不同价格的后续行。希望这是有道理的。

4

3 回答 3

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

我已经给出了这两种类型的年龄,并说明了表中仅存在一次的项目(它们没有旧日期)。请让我们知道这有多接近。

更新:我必须更正“PriceAgeToNow”中的日期计算,并且我还尝试过滤掉只有 1 天的新价格的记录。这是SQL 小提琴

-- 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 回答
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

对于在数据中保持不变的任何价格序列,最后两列之间的差异是不变的。然后我们可以使用它来查找该序列何时开始。以下查询采用这种方法:

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 回答