根据规则更新col值

时间:2018-04-05 09:30:11

标签: sql sql-server tsql

我有值和colrank列的表,值是特定id的值,rank是整个记录中特定id的百分比。

我想更新2个条件的记录,比如

  1. 其中colrank大于0.95然后将值更新为最近colrank值的相应值< = 0.95
  2. 其中colrank小于0.5然后将值更新为nearset colrank的相应值> = 0.5

    declare @tbl table (id int , value float , colrank float );
    
    insert into @tbl
    values(1,10, 0.52),
          (2,11, 0.48),
          (3,18, 0.94),
          (4,22, 0.96);
    
    select * from @tbl;
    
  3. 我的代码在下面,但我不满意,因为我多次使用同一张表。请建议最好的方法。

    ;WITH CTE AS 
    (
    SELECT MAX(colrank ) high 
    FROM @tbl 
    where   colrank <= 0.95
    ), 
    cte1 as (
    SELECT min(colrank ) low 
    FROM @tbl 
    where   colrank <= 0.5
    )  
    
    select * from cte ,cte1 
    

4 个答案:

答案 0 :(得分:2)

您可以使用条件聚合来避免在同一数据集下进行双重迭代:

SELECT MAX(CASE WHEN colrank <= 0.95 THEN colrank END) high,
       MIN(CASE WHEN colrank <= 0.5 THEN colrank END) low 
FROM @tbl;

DEMO

答案 1 :(得分:2)

这很有趣。我试过,我明白这可能不是最好的解决方案,仍然发布,因为它满足所有情况:sql fiddle

create table tbl (id int , value float , colrank float );
insert into tbl
values(1,10, 0.52),
      (2,11, 0.54),
      (3,12, 0.48),
      (4,13, 0.49),
      (5,17, 0.93),
      (6,18, 0.94),
      (7,22, 0.96);

WITH CTE AS
( (SELECT TOP 1 *,1 as [rank] from tbl WHERE colrank < 0.95 ORDER BY colrank DESC)
   UNION
  (SELECT TOP 1 *,2 as [rank] from tbl WHERE colrank > 0.50 ORDER BY colrank ASC)
 )
  SELECT 
    b.id, b.value, b.colrank, a.value
  FROM 
    tbl b 
  LEFT JOIN cte a
  ON 
    (CASE WHEN b.colrank < 0.5 and a.[rank] = 2 THEN 1
        WHEN b.colrank > 0.95 and a.[rank] = 1 THEN 1
    END) = 1
  WHERE a.value IS NOT NULL

更新只需用以下更新语法替换select:

WITH CTE AS
( (SELECT TOP 1 *,1 as [rank] from tbl WHERE colrank < 0.95 ORDER BY colrank DESC)
   UNION
  (SELECT TOP 1 *,2 as [rank] from tbl WHERE colrank > 0.50 ORDER BY colrank ASC)
 )
  UPDATE b
  SET b.value = a.value
  FROM 
    tbl b 
  LEFT JOIN cte a
  ON 
    (CASE WHEN b.colrank < 0.5 and a.[rank] = 2 THEN 1
        WHEN b.colrank > 0.95 and a.[rank] = 1 THEN 1
    END) = 1
  WHERE a.value IS NOT NULL

答案 2 :(得分:2)

具有UPDATE语句的简单CASE将在此方案中起作用。尝试查询如下。

UPDATE T
SET T.Value =
   (
      CASE WHEN T.colrank > 0.95 THEN (SELECT TOP 1 VALUE FROM @tbl T1
                         WHERE T1.colrank <= 0.95 ORDER BY T1.colrank DESC)
      WHEN T.colrank < 0.5 THEN (SELECT TOP 1 VALUE FROM @tbl T2 
                         WHERE T2.colrank >= 0.5 ORDER BY T2.colrank)
      ELSE T.value
      END
   )
FROM @tbl T

DEMO

答案 3 :(得分:0)

这是两次更新,但仍然有效。

declare @tbl table (id int , value float , colrank float );
insert into @tbl
values(1, 10, 0.52),
      (2, 11, 0.48),
      (3, 18, 0.94),
      (4, 22, 0.96);
declare @min float = (select min(colrank) from @tbl where colrank >= 0.5);
declare @max float = (select max(colrank) from @tbl where colrank <= 0.95);
select * from @tbl;
update @tbl set colrank = @min where colrank < @min;
update @tbl set colrank = @max where colrank > @max;
select * from @tbl;

id          value                  colrank
----------- ---------------------- ----------------------
1           10                     0.52
2           11                     0.48
3           18                     0.94
4           22                     0.96

id          value                  colrank
----------- ---------------------- ----------------------
1           10                     0.52
2           11                     0.52
3           18                     0.94
4           22                     0.94