从另一个表更新一个具有接近值的表

时间:2017-05-09 19:44:03

标签: mysql

我有两张桌子。

Products
------------

ID | Sales | Rank
==================
1  | 0     | 100
2  | 0     | 105
3  | 0     | 200
4  | 0     | 900

Sales

ID | Sales | Rank
==================
1  | 2000     | 99
2  | 5000     | 106
3  | 8000     | 800
4  | 2500     | 950

我想根据排名更新sales.sales与sales.sales。例如

set products.sales=sales.sales where sales.sales is nearest to product.sales

在上面的例子中,下面将是查询的结果。

Products
------------

ID | Sales | Rank
==================
1  | 2000     | 100
2  | 5000     | 105
3  | 5000     | 200
4  | 2500     | 900

尝试根据排名从销售表中查找产品的销售情况,如果找不到,则找到Product.Rank对sales.rank最近值的任何内容。

感谢

1 个答案:

答案 0 :(得分:0)

因为MySQL没有窗口功能,所以你必须采用"艰难的方式"。首先,构建一个查询,计算每个产品等级的最小差异:

select p.rank, min(abs(s.rank - p.rank)) diff
from sales s
cross join products p
group by 1

然后使用它来找到哪个等级最接近,找到具有该差异的等级,再次加入并丢弃除最高sales之外的所有等级以打破关系:

update Products
join (select p.rank, min(abs(s.rank - p.rank)) diff
     from Sales s
     cross join Products p
     group by 1) x on Products.rank = x.rank
join Sales s1 on abs(Products.rank - s1.rank) = x.diff
left join Sales s2 on abs(Products.rank - s2.rank) = x.diff
    and s2.sales > s1.sales
    and s1.rank != s2.rank
set Products.sales = s1.sales
where s2.rank is null

由于SQLFiddle已关闭计数,因此这里是完整的脚本:

create table Products (ID int, Sales int, Rank int); 
insert into Products values 
(1,0,100),
(2,0,105),
(3,0,200),
(4,0,900);

create table Sales (ID int, Sales int, Rank int); 
insert into Sales values 
(1,2000,99),
(2,5000,106),
(3,8000,800),
(4,2500,950);

update Products
join (select p.rank, min(abs(s.rank - p.rank)) diff
     from Sales s
     cross join Products p
     group by 1) x on Products.rank = x.rank
join Sales s1 on abs(Products.rank - s1.rank) = x.diff
left join Sales s2 on abs(Products.rank - s2.rank) = x.diff
    and s2.sales > s1.sales
    and s1.rank != s2.rank
set Products.sales = s1.sales
where s2.rank is null;

select * from Products;

输出:

+------+-------+------+
| ID   | Sales | Rank |
+------+-------+------+
|    1 |  2000 |  100 |
|    2 |  5000 |  105 |
|    3 |  5000 |  200 |
|    4 |  2500 |  900 |
+------+-------+------+