You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SQL Server 2017:如何依据最后记录值替换所有历史值

解决SQL Server 2017中基于Person最后交易状态生成布尔列的问题

我来帮你搞定这个需求!你需要根据每个Person的最后一条交易记录的Status,生成is_Openis_Closed两个布尔列,咱们一步一步来实现。

核心思路

要实现这个需求,我们需要先获取每个Person的最后一条交易记录的状态及对应日期,再将这个结果关联回原表,结合两条规则判断每条记录的布尔值:

  • is_Open:仅当Person的最后状态是Open,且当前记录是该Person的最后一条交易时,值为1,其余情况为0
  • is_Closed:仅当Person的最后状态是Closed,且当前记录是该Person的最后一条交易时,值为1,其余情况为0

完整解决方案代码

declare @T1 table ( ClaimID int, Person varchar(20), TransactionDate date, Status varchar(20) )
insert into @T1 values
(1, 'Person1', '2018-03-05','Open')
,(1, 'Person2', '2018-03-10','Open')
,(1, 'Person2', '2018-03-15','Closed')
,(2, 'Person3', '2018-03-15','Open')
,(2, 'Person3', '2018-03-23','Closed')
,(3, 'Person4', '2018-04-18','Closed')
,(4, 'Person5', '2018-04-23','Open')
,(4, 'Person5', '2018-04-25','Open')

-- 使用CTE获取每个Person的最后交易状态和日期
WITH PersonLastTransaction AS (
    SELECT 
        Person,
        Status AS LastStatus,
        TransactionDate AS LastTransactionDate,
        -- 给每个Person的交易按日期倒序排号,第1条就是最后一条交易
        ROW_NUMBER() OVER (PARTITION BY Person ORDER BY TransactionDate DESC) AS RowRank
    FROM @T1
    WHERE TransactionDate <= '2018-12-31'
)
SELECT 
    t.*,
    -- 计算is_Open列
    CASE
        WHEN plt.LastStatus = 'Open' AND t.TransactionDate = plt.LastTransactionDate THEN 1
        ELSE 0
    END AS is_Open,
    -- 计算is_Closed列
    CASE
        WHEN plt.LastStatus = 'Closed' AND t.TransactionDate = plt.LastTransactionDate THEN 1
        ELSE 0
    END AS is_Closed
FROM @T1 t
-- 关联每个Person的最后交易信息
JOIN PersonLastTransaction plt ON t.Person = plt.Person AND plt.RowRank = 1
WHERE t.TransactionDate <= '2018-12-31'
ORDER BY t.ClaimID, t.TransactionDate;

为什么你的尝试没生效?

你之前用LAST_VALUE的问题主要有两点:

  1. 窗口框架默认行为限制LAST_VALUE默认的窗口框架是RANGE BETWEEN CURRENT ROW AND CURRENT ROW,只会取当前行的值,而非整个Person分区的最后一条记录状态。如果要让它取到整个分区的最后状态,需要显式指定窗口框架:LAST_VALUE(Status) OVER (PARTITION BY Person ORDER BY TransactionDate DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
  2. 缺少最后记录判断:就算正确获取了最后状态,还需要判断当前记录是否是该Person的最后一条交易,否则会出现所有记录都根据最后状态赋值的情况,不符合“仅最后一条记录为1,其余为0”的规则。

测试结果

运行上述代码后,输出完全符合需求:

ClaimIDPersonTransactionDateStatusis_Openis_Closed
1Person12018-03-05Open10
1Person22018-03-10Open00
1Person22018-03-15Closed01
2Person32018-03-15Open00
2Person32018-03-23Closed01
3Person42018-04-18Closed01
4Person52018-04-23Open00
4Person52018-04-25Open10

内容的提问来源于stack exchange,提问作者Serdia

火山引擎 最新活动