美好的一天,
我在SSMS中使用MS T-SQL。我试图确定一种基于变量或case语句的窗口函数的方法。我需要窗口继续循环,直到某个结果发生,然后通过这些观察切割窗口。另外,也许有更好的方法在Windows之外做这个,我已经研究了WHILE表达式作为潜在的选项。
以下是一个示例数据集:
CREATE TABLE #Items ([Transaction] int, [Item] varchar(10), [Price] money, [Price2] varchar(25), [SaleDate] smalldatetime)
INSERT INTO #Items ([Transaction], [Item], [Price], [Price2], [SaleDate])
VALUES (123,'Blue',1100,'Blue1100','04/10/2018'),
(124,'Blue',1100,'Blue1100','04/09/2018'),
(125,'Blue',1100,'Blue1100','04/09/2018'),
(126,'Blue',3000,'Blue3000','03/27/2018'),
(127,'Blue',1100,'Blue1100','03/27/2018'),
(128,'Blue',1100,'Blue1100','03/27/2018'),
(129,'Blue',1100,'Blue1100','03/27/2018'),
(130,'Blue',1100,'Blue1100','03/27/2018'),
(131,'Red',3328,'Red3328','04/12/2018'),
(132,'Red',3328,'Red3328','04/09/2018'),
(133,'Red',3328,'Red3328','04/06/2018'),
(134,'Red',3328,'Red3328','04/04/2018'),
(135,'Red',3328,'Red3328','04/02/2018'),
(136,'Red',3328,'Red3328','04/02/2018'),
(137,'Yellow',1340,'Yellow1340','04/09/2018'),
(138,'Yellow',1340,'Yellow1340','04/08/2018'),
(139,'Yellow',1340,'Yellow1340','04/08/2018'),
(140,'Yellow',1500,'Yellow1500','04/05/2018'),
(141,'Yellow',1340,'Yellow1340','04/05/2018'),
(142,'Yellow',1340,'Yellow1340','04/05/2018'),
(143,'Yellow',1340,'Yellow1340','04/02/2018'),
(144,'Yellow',1340,'Yellow1340','03/31/2018')
在这种情况下,我希望窗口查看按[SaleDate] desc排序的每个[Item],并按顺序创建具有相同[Price]的顺序的窗口大小。只要[价格]没有中断,窗口就会基于这些观察。一旦确定了,我想添加一个列,在窗口中为这些观察结果提供最小的[SaleDate]。
我正在尝试使用以下查询,但无法弄清楚如何让窗口循环:
SELECT
Transaction
, Item
, Price
,Price2
, SaleDate
,(CASE WHEN PRICE2 = LEAD(PRICE2) OVER (ORDER BY Price ASC, SaleDate DESC )
AND LEAD(PRICE2) OVER (ORDER BY Price ASC, SaleDate DESC ) = LEAD(PRICE2) OVER (ORDER BY Price ASC, SaleDate DESC )
THEN MIN(SaleDate) ELSE NULL END) 'StartDate'
FROM #Items
GROUP BY
Transaction
, Item
, Price
,Price2
, SaleDate
欢迎任何和所有建议!谢谢!
答案 0 :(得分:2)
这可以通过递归CTE完成。
示例SQL:
;with CTE as (
SELECT [Transaction], Item, Price, Price2, SaleDate,
row_number() over (partition by Item order by SaleDate asc, [Transaction] desc) as rn
FROM #Items
)
, RCTE as (
SELECT
c.*,
SaleDate as SaleDatePriceChange
from CTE c
where rn = 1
union all
SELECT
c.*,
case when c.Price = r.Price then r.SaleDatePriceChange else c.SaleDate end
from RCTE r
join CTE c on c.Item = r.Item and c.rn = r.rn + 1
)
select [Transaction], Item, Price, Price2, SaleDate, SaleDatePriceChange
from RCTE
order by Item, rn desc;
第一个CTE用于添加row_number。
这样可以更轻松地加入递归CTE中的下一条记录。
答案 1 :(得分:0)
这是获取这些开始日期的另一种方法 这次没有递归。
它使用LAG获取前一记录的价格 这样以前的价格就可以与记录的价格进行比较 如果价格发生变化,IIF将返回1,否则返回0。
SUM窗口函数将向上添加1和0,从而产生排名 诀窍是,当添加0时,等级数不会增加。
然后FIRST_VALUE用于获取其中排名第一的SaleDate。
select
[Transaction], Item, Price, Price2, SaleDate,
first_value(t.SaleDate) over (partition by t.Item, q2.PriceChangeRank order by t.SaleDate, t.[Transaction] desc) as PriceChangedDate
from
(
select TransactionID,
sum(PriceChanged) over (partition by Item order by SaleDate, TransactionID desc) as PriceChangeRank
from
(
select [Transaction] as TransactionID, Item, SaleDate,
iif(Price != lag(Price) over (partition by Item order by SaleDate, [Transaction] desc),1,0) as PriceChanged
from #Items
) q1
) q2
join #Items t on (t.[Transaction] = q2.TransactionID)
order by [Transaction];
不确定此方法是否比使用动态SQL更快。 但它是另一种选择。