根据interval - SQL将整数值分配给行

时间:2014-09-19 22:12:20

标签: sql

我有一个如下所示的MySQL数据集:

a     b
.32   .72
.41   .80
.28   .64
.31   .80

我想根据a和b的条件为每一行分配值( c ):

.3< a< .4和.71< b< .83 = 1

.4< a< .5和.71< b< .83 = 2

.2< a< .3和.58< b< .77 = 3

等等。这会导致我的表格看起来像这样:

a     b     c
.32   .72   1
.41   .80   2
.28   .64   3
.31   .80   1

我该怎么做?我已经尝试了一个案例,当时()声明但是没有用,因为我不知道如何/如果有可能有一个有多个案例的那个。

3 个答案:

答案 0 :(得分:2)

我不完全理解这一点:我在()语句中尝试了一个案例,但由于我不知道如果有可能有一个多于一个案例。

这将为您提供您描述的输出。我有点懒/累,所以我只是粘贴SQL Fiddle的输出:

SQL Fiddle

MySQL 5.5.32架构设置

CREATE TABLE Table1
    (`a` decimal(2,2), `b` decimal(2,2))
;

INSERT INTO Table1
    (`a`, `b`)
VALUES
    (.32, .72),
    (.41, .80),
    (.28, .64),
    (.31, .80)
;

alter table table1 add column c int;

update table1
set c = 
case 
  when (.3 < a and a < .4) and (.71 < b and b < .83) then  1
  when (.4 < a and a < .5) and (.71 < b and b < .83) then  2
  when (.2 < a and a < .3) and (.58 < b and b < .77) then  3
end;

查询1

select * from table1

<强> Results

|    A |    B | C |
|------|------|---|
| 0.32 | 0.72 | 1 |
| 0.41 |  0.8 | 2 |
| 0.28 | 0.64 | 3 |
| 0.31 |  0.8 | 1 |

答案 1 :(得分:1)

您不会说出您正在使用的SQL实现。

如果您正在使用SQL Server,则可以添加计算列,如下所示:

create table foo
(
  int a not null ,
  int b not null ,

  c as case
       when a > 0.3 and a < 0.4 and b > 0.71 and b < 0.83 then 1
       when a > 0.4 and a < 0.5 and b > 0.71 and b < 0.83 then 2
       when a > 0.2 and a < 0.3 and b > 0.58 and b < 0.77 then 3
       else null // anything that doesn't match one of the above tests
       end ,

)

如果你不能做那样的话,你可以创建一个视图

create table foo
(
  int a not null ,
  int b not null ,
)
create view foo_view as
select foo.* ,
       case
       when a > 0.3 and a < 0.4 and b > 0.71 and b < 0.83 then 1
       when a > 0.4 and a < 0.5 and b > 0.71 and b < 0.83 then 2
       when a > 0.2 and a < 0.3 and b > 0.58 and b < 0.77 then 3
       else null // anything that doesn't match one of the above tests
       end as c

确保您的计算c始终与基础数据同步。

如果你采用更新路线,那么这个版本就不那么难了:

update foo 
set c = case
        when a > 0.3 and a < 0.4 and b > 0.71 and b < 0.83 then 1
        when a > 0.4 and a < 0.5 and b > 0.71 and b < 0.83 then 2
        when a > 0.2 and a < 0.3 and b > 0.58 and b < 0.77 then 3
        else null // anything that doesn't match one of the above tests
        end

虽然您可以考虑在表格上添加更新触发器,以自动更新c,然后ab更改值。

答案 2 :(得分:1)

我会创建一个辅助表并使用它来驱动更新。

一般来说,尝试将这样的事情参数化为表格,而不是制作一个大的鸣叫sql。

这仍然留给您一个问题,即您的标准是否存在矛盾(即可能有多种结果,没有结果等等),但在sql和可维护性方面更清晰。

我已经分别处理了存在和下限1的结果/多个结果,因此至少他们不会出错。

drop table tgt;
create table tgt(a float, b float, calc int);

drop table range;
create table range(a_low float, a_high float, 
b_low float, b_high float, calc float);

select * from tgt;

insert into tgt (a,b, calc) values(.32,   .72, 0);
insert into tgt values(.41,   .80, 0);
insert into tgt values(.28,  .64, 0);
insert into tgt values(.31,   .80, 0);

/*
3 < a < .4 and .71 < b < .83 = 1

.4 < a < .5 and .71 < b < .83 = 2

.2 < a < .3 and .58 < b < .77 = 3
*/

insert into range (a_low, a_high, b_low, b_high, calc) 
values (.3, .4, .71, .83, 1);
insert into range (a_low, a_high, b_low, b_high, calc) 
values (.4, .5, .71, .83, 2);
insert into range (a_low, a_high, b_low, b_high, calc) 
values (.2, .3, .58, .77, 3);


select * from tgt;

update tgt
set calc =
(select calc 
from range 
where tgt.a 
between range.a_low and range.a_high 
and tgt.b between range.b_low and range.b_high 
/* limit is to avoid 
if error if multiple results 
- picks only one
*/
limit 1)
where 
/* and exists avoids it if there are no results */
exists
(select calc 
from range 
where tgt.a 
between range.a_low and range.a_high 
and tgt.b between range.b_low and range.b_high)

;

select * from tgt;
在postgresql中

这是结果:

0.32; 0.72; 1

0.41; 0.8; 2

0.28; 0.64; 3

0.31; 0.8; 1