【问题标题】:T-SQL: Self-Referencing calculated fieldT-SQL:自引用计算字段
【发布时间】:2021-04-07 13:21:09
【问题描述】:

我正在尝试根据现有表格计算每日日内交易总数,该表格提供滚动五天窗口(仅限工作日)内的日内交易累计数。数据集非常简单,但是,如果不求助于无尽的子查询链,我似乎无法计算它。具有挑战性的部分是,在每个交易日结束时,五天前的当日交易总数现在到期并从滚动总数中删除。

这是我的数据集(表格):

这是我需要的最终结果:

请注意,底部以黄色突出显示的前四行(最旧的日期)非常容易计算,因为 11/09 是起点,之前没有当日交易,因此不会删除任何当日交易(过期)直到四个工作日后(11 月 13 日)。

从那里,我不知道该怎么办。似乎我尝试的任何东西都只是一个计算字段,需要在过去四行引用它自己(它自己的结果)。至少,部分计算会。计算本质上只是 = [截至今天的累积“日内交易”-(截至前一天的累积“日内交易”-四天前的“每日总计”)]。同样,数据集仅包含开始的工作日。递归 CTE 会为此工作吗?

备注 1:我不需要滚动累积“日间交易”字段的帮助。这已经为我自动填充了。我只需要“每日总计”的临时计算帮助(每天的新日交易。

备注 2:“日内交易”只是在同一天买入和卖出同一只股票。它是同一股票的买入和卖出订单的一对一匹配。

备注 3:解决方案需要与 IBM Netezza 规则兼容,最好。

【问题讨论】:

  • 请避免使用图片。将示例数据作为格式化文本发布
  • 窗口函数SUM(...) OVER (PARTITION BY ... ORDER BY date ROWS 4 PRECEDING)
  • 要每天更新滚动号码,您必须每晚运行更新作业
  • 请提供一些关于如何计算daily_total 的示例
  • 另外,预计会缺少工作日吗?我在您的示例数据中找不到 2020-11-26 THU

标签: sql-server tsql recursion recursive-query self-reference


【解决方案1】:

这可能不是最优雅的解决方案,但它应该给出正确的答案。

DECLARE @currentDate date 
DECLARE @expiredTrades int 
DECLARE @yesterday int
DECLARE @salesDataTable TABLE
(
    dates date,
    day_trades int,
    daily_total int NULL
)

INSERT INTO @salesDataTable (dates, day_tradeS, daily_total) VALUES
('2019-01-01', 10, 10),
('2019-01-02', 27, 17),
('2019-01-03', 28, 1),
('2019-01-04', 28, 0),
('2019-01-05', 24, NULL),
('2019-01-06', 7, NULL),
('2019-01-07', 11, NULL),
('2019-01-08', 11, NULL),
('2019-01-09', 18, NULL),
('2019-01-10', 18, NULL),
('2019-01-11', 56, NULL),
('2019-01-12', 61, NULL),
('2019-01-13', 56, NULL),
('2019-01-14', 68, NULL),
('2019-01-15', 48, NULL),
('2019-01-16', 52, NULL),
('2019-01-17', 54, NULL)

WHILE 1 = (SELECT TOP 1 1 FROM @salesDataTable WHERE daily_total IS NULL)
BEGIN
    SELECT TOP 1 @currentDate = dates
    FROM @salesDataTable
    WHERE daily_total IS NULL
    ORDER BY dates
    
    SELECT 
        @expiredTrades = LAG (daily_total, 4, 0) OVER (ORDER BY dates),
        @yesterday = LAG (day_trades, 1, 0) OVER (ORDER BY dates)
    FROM @salesDataTable
    WHERE dates <= @currentDate

    UPDATE @salesDataTable
    SET daily_total = day_trades - (@yesterday - @expiredTrades)
    WHERE dates = @currentDate
END

SELECT * 
FROM @salesDataTable

【讨论】:

  • @tshobe 解决了您的问题吗?如果是这样 - 您应该将其标记为答案。所以人们知道问题已经解决了。
【解决方案2】:
declare @t table(dates date, day_trades int);

insert into @t(dates, day_trades)
values
('20201109', 10), ('20201110', 27), ('20201111', 28), ('20201112', 28), ('20201113', 24),
('20201116', 7), ('20201117', 11), ('20201118', 11), ('20201119', 18), ('20201120', 18),
('20201123', 56), ('20201124', 61), ('20201125', 56), ('20201127', 68), ('20201130', 48),
('20201201', 52), ('20201202', 54);


select dates, day_trades, sum(prevdiff) over(partition by grp order by dates) as dailytotal
from
(
select *, 
    row_number() over(order by dates)%4 as grp,
    day_trades - lag(day_trades, 1, 0) over(order by dates) as prevdiff
from @t
) as t
order by dates desc

【讨论】:

  • 这太棒了,太简单了!!谢谢你,lptr!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 1970-01-01
  • 2011-03-28
  • 2014-08-14
  • 2020-04-08
  • 2018-04-09
  • 1970-01-01
相关资源
最近更新 更多