Sql server 基于SQL Server中的其他列值推断一列的值
如果一天的运行速度>0,则其状态为true 如果某一天没有数据,则推断另一天的最后状态代码 记录表值中的列,如果该值为零,则将运行状态标记为true。对于非零标记状态的代码,状态为false 见下表Sql server 基于SQL Server中的其他列值推断一列的值,sql-server,tsql,Sql Server,Tsql,如果一天的运行速度>0,则其状态为true 如果某一天没有数据,则推断另一天的最后状态代码 记录表值中的列,如果该值为零,则将运行状态标记为true。对于非零标记状态的代码,状态为false 见下表 Day Run speed Statuscode Status --------------------------------------- 1-Jan-14 55 0 TRUE 2-Jan-14 60 0
Day Run speed Statuscode Status
---------------------------------------
1-Jan-14 55 0 TRUE
2-Jan-14 60 0 TRUE
3-Jan-14 58 0 TRUE
4-Jan-14 61 0 TRUE
5-Jan-14 57 0 TRUE
6-Jan-14 56 0 TRUE
7-Jan-14 60 0 TRUE
8-Jan-14 TRUE
9-Jan-14 TRUE
10-Jan-14 55 0 TRUE
11-Jan-14 56 0 TRUE
12-Jan-14 60 0 TRUE
13-Jan-14 0 20 FALSE
例8-jan-14/9-jan-14没有值,但自从上次记录第7次以来,这是真的,这就是为什么这两个日期的状态也是真的。外部应用将解决第二个需求
在我看来,APPLY、crossapply和outerapply是最容易理解和利用率最低的迭代器。但是一旦你掌握了它们的力量并理解了用例,它们就会成为你工具箱中的致命武器。它们在TOPn(按某些逻辑)情况下特别有用,在这种情况下,内置函数无法满足您的需求
注意使用位表示布尔真/假
您真正想要的是忽略空值,但SQL Server不支持这一点 您可以使用另一种技巧,即获取状态为0的最长日期和状态不为0的最长日期,并进行比较。因此:
select t.*,
(case when statuscode = 0 then 'TRUE'
when statuscode <> 0 then 'FALSE'
when (max(case when statuscode = 0 then day end) over (order by day) >
coalesce(max(case when statuscode <> 0 day date end) over (order by day), '2000-01-01')
)
then 'TRUE'
else 'FALSE'
end) as status
from t;
他是一把小提琴
实际上,您可以将其简化为最后的条件:
select t.*,
(case when (max(case when statuscode = 0 then day end) over (order by day) >
coalesce(max(case when statuscode <> 0 then day end) over (order by day), '2000-01-01')
)
then 'TRUE'
else 'FALSE'
end) as status
from t;
第一个版本更好地遵循您描述的逻辑
我无法从这个问题判断您是想将逻辑基于runningspeed还是statuscode。运行速度的逻辑非常相似。使用外部应用作为更灵活的延迟
现场测试:
获取第一部分很容易,就像您提到的,如果大于0,我们可以将其设置为真。但我面临的困难是在第二部分,即如果没有数据,我们必须返回并检查最后记录的代码是否为0。该部分也可以非常简单。你的平台是什么?SQL Server?但是使用滞后,您通过将偏移量设置为1来指定只返回一个。但是我们不知道它是否只有1天或更长。如果您以前的逻辑比滞后所能提供的更复杂,您可以应用它。您发布了要求,但您忘记了包含您的工作和问题。
select t.*,
(case when (max(case when statuscode = 0 then day end) over (order by day) >
coalesce(max(case when statuscode <> 0 then day end) over (order by day), '2000-01-01')
)
then 'TRUE'
else 'FALSE'
end) as status
from t;
select
o.*,
Status =
convert(bit,
case
when o.RunningSpeed > 0
or o.RunningSpeed is null and prev.StatusCode = 0 then
1
else
0
end)
from tbl o
outer apply
(
select top 1 StatusCode
from tbl i
where i.Day < o.Day and i.StatusCode is not null
order by i.Day desc
) prev
| Day | RunningSpeed | Statuscode | Status |
|----------------------|--------------|------------|--------|
| 2014-01-01T00:00:00Z | 55 | 0 | true |
| 2014-01-02T00:00:00Z | 60 | 0 | true |
| 2014-01-03T00:00:00Z | 58 | 0 | true |
| 2014-01-04T00:00:00Z | 61 | 0 | true |
| 2014-01-05T00:00:00Z | 57 | 0 | true |
| 2014-01-06T00:00:00Z | 56 | 0 | true |
| 2014-01-07T00:00:00Z | 60 | 0 | true |
| 2014-01-08T00:00:00Z | (null) | (null) | true |
| 2014-01-09T00:00:00Z | (null) | (null) | true |
| 2014-01-10T00:00:00Z | 55 | 0 | true |
| 2014-01-11T00:00:00Z | 56 | 0 | true |
| 2014-01-12T00:00:00Z | 60 | 0 | true |
| 2014-01-13T00:00:00Z | 0 | 20 | false |