Sql server 基于SQL Server中的其他列值推断一列的值

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

如果一天的运行速度>0,则其状态为true

如果某一天没有数据,则推断另一天的最后状态代码 记录表值中的列,如果该值为零,则将运行状态标记为true。对于非零标记状态的代码,状态为false

见下表

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 |