简体   繁体   English

SQL 显示之前的值,直到给定值改变

[英]SQL Show the previous value until the given value changes

I have a table ordered by ID with column Value .我有一个按ID排序的表,其中包含Value列。

| ID       | Value          |
| -------- | -------------- |
| 1        | 50             |
| 2        | 50             |
| 3        | 62             |
| 4        | 62             |
| 5        | 62             |
| 6        | 79             |
| 7        | 90             |
| 8        | 90             |

I would like to create another column Prev_Value that for each row of column Value takes the previous/preceding number that differs from the current row value, as in the table below.我想创建另一列Prev_Value ,对于列Value的每一行,它采用与当前行值不同的前一个/前一个数字,如下表所示。

Output table: Output表:

| ID       | Value          |Prev_Value     |
| -------- | -------------- |---------------|
| 1        | 50             |NULL           |
| 2        | 50             |NULL           |
| 3        | 62             |50             |
| 4        | 62             |50             |
| 5        | 62             |50             |
| 6        | 79             |62             |
| 7        | 90             |79             |
| 8        | 90             |79             |

Should I use modified LAG() function, the CROSS APPLY or nested CASE and what approach would be the most time-efficient?我应该使用修改后的 LAG() function、CROSS APPLY 还是嵌套 CASE,哪种方法最省时? Any help would be appreciated.任何帮助,将不胜感激。

Here are some references that unfortunately does not solve my problem: LAG(offset) until value is reached in BigQuery and SQL Server: select distinct until the value is changed以下是一些不幸无法解决我的问题的参考: LAG(offset) until value is reached in BigQuery and SQL Server: select distinct until the value is changed

One method uses apply :一种方法使用apply

select t.*, tprev.value
from t outer apply
     (select top (1) tprev.*
      from t tprev
      where tprev.value <> t.value and
            tprev.id < t.id
      order by tprev.id desc
     ) tprev;

The above is not the most efficient method on a large dataset.以上不是大型数据集上最有效的方法。 For that, I would suggest getting the first time that a value changes and marking that.为此,我建议第一次获得值更改并标记它。

select t.*,
        max(case when prev_value <> value then prev_value end) over (partition by grp) as prev_value
from (select t.*,
             sum(case when prev_value = value then 0 else 1 end) over (order by id) as grp
      from (select t.*,
                   lag(value) over (order by id) as prev_value
            from t
           ) t
     ) t;

Here is a db<>fiddle. 是一个 db<>fiddle。

Here is one way to do it.这是一种方法。 (Check it live on this fiddle ) (在这个小提琴上检查它)

 select 
    t1.*, 
    t2.value prev_value  
from 
    t t1 
    left join t t2 on t2.id = (select max(id) from t where value<t1.value)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM