【问题标题】:Assign integer value to row based on interval - SQL根据间隔为行分配整数值 - SQL
【发布时间】:2014-09-20 08:40:23
【问题描述】:

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

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

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

.3

.4

.2

等等。这将导致我的表格如下所示:

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

我该怎么做?我尝试了 case when() 语句,但没有奏效,因为我不知道如何/是否有可能让其中一个有多个案例。

【问题讨论】:

  • 如果 WHEN 不适合您,请使用 IF 语句:stackoverflow.com/questions/9648481/…
  • 我不知道你是如何在基于 a 和 b 列数据的条件下得到这个数字的?
  • @Miki 我不明白你在问什么
  • .3 基于您在条件下使用 .71 和 .83 的情况?
  • 哦,那是我自己的号码。我可以选择任何东西。

标签: sql


【解决方案1】:

我不完全理解这一点:我尝试了 case when() 语句,但没有奏效,因为我不知道如何/是否有可能拥有一个以上的语句案例。

这将为您提供您所描述的输出。我有点懒/累了,所以我只粘贴 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 |

【讨论】:

  • 您可以选择 a, b, (case statements) as c from table,而不是单独的列
  • @Rajesh 确实如此,但我的印象是 OP 想添加一个新列。
  • 对,问题不清楚,我这边+1
  • 是的......我意识到我在做 case when() 语句错误。这样可行。谢谢!
【解决方案2】:

你没有说你正在使用什么 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 更改值。

【讨论】:

  • OP 在问题的顶部声明它是 Mysql。不过好点,我只是把它当作一次性手术。
【解决方案3】:

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

一般来说,尝试将这样的东西参数化到表中,而不是制作一个大的喇叭 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    • 2020-06-14
    • 2023-02-25
    • 2020-03-19
    • 2022-01-17
    • 1970-01-01
    相关资源
    最近更新 更多