简体   繁体   English

使用不同查找表中的值更新 SQL Server 中的列?

[英]Update an column in SQL Server with values from a different lookup table?

I'm working on a project where I need to update a Mailing Rate column that is currently blank.我正在处理一个项目,我需要更新当前为空白的邮寄费率列。 I have a few different tables of rates/costs based on type of delivery service.根据送货服务的类型,我有几个不同的费率/成本表。 Within each table is essentially a table of weights and zones where the cost depends on weight (y column) and distance travelled (x column).每个表中基本上都有一个重量和区域表,其中成本取决于重量(y 列)和行驶距离(x 列)。

The table I need to update lists the various types of delivery service, associated weight and associated distance travelled for each piece of mail.我需要更新的表格列出了每封邮件的各种递送服务类型、相关重量和相关距离。 I'm having trouble figuring out the logic on how to write a query to update the rates column in this table that match the corresponding tables' lookup of weight/travel distance for each service.我无法弄清楚如何编写查询以更新此表中与相应表对每项服务的重量/行程距离查找相匹配的 rate 列的逻辑。

Below is an example of the tables:以下是表的示例:

| Type of Service |  Weight  | Distance |   Cost   |
+-----------------+----------+----------+----------+
| A               | 1        | 15       | ?        |
| B               | 2        | 20       | ?        |
| C               | 3        | 10       | ?        |
|                 |          |          |          |
| Service A Table |          |          |          |
| Weight          | 10 km    | 15 km    | 20 km    |
| 1               |  $25.00  |  $30.00  |  $40.00  |
| 2               |  $27.00  |  $32.00  |  $41.00  |
| 3               |  $28.00  |  $34.00  |  $43.00  |
|                 |          |          |          |
| Service B Table |          |          |          |
| Weight          | 10 km    | 15 km    | 20 km    |
| 1               |  $28.00  |  $32.00  |  $41.00  |
| 2               |  $29.00  |  $35.00  |  $44.00  |
| 3               |  $30.00  |  $37.00  |  $47.00  |
+-----------------+----------+----------+----------+

You can use a MERGE statement between your main table you want to calculate the cost for and the services table.您可以在要计算成本的主表和服务表之间使用MERGE语句。 Do the merge on weight and distance and calculate the costs based on service type.进行重量和距离的合并,并根据服务类型计算成本。

Consult the merge documentation it should be very easy to do it.查阅合并文档应该很容易做到。 I could do it on here but better learning for you.我可以在这里做,但更好地为你学习。

Here there is an example: https://www.sqlservertutorial.net/sql-server-basics/sql-server-merge/这里有一个例子: https : //www.sqlservertutorial.net/sql-server-basics/sql-server-merge/

You can use left join to bring in all the tables .您可以使用left join引入所有表。 . . . . and a lot of case logic to choose the columns:以及很多case逻辑来选择列:

update t
    set cost = (case when distance = '10 km'
                     then coalesce(sa.10km, sb.10km, sc.10km)
                     when distance = '15 km'
                     then coalesce(sa.15km, sb.15km, sc.15km)
                     when distance = '20 km'
                     then coalesce(sa.20km, sb.20km, sc.20km)
                end)
from t left join
     servicea sa
     on sa.weight = t.weight and t.service = 'A' left join
     servicea sb
     on sb.weight = t.weight and t.service = 'B' left join
     servicea sc
     on sc.weight = t.weight and t.service = 'C' ;

Since you have different tables for each type of service it is going to be hard for you if you add new types of service.由于每种类型的服务都有不同的表,因此如果添加新类型的服务对您来说会很困难。 Optimally the type of service would be a column in one table for the costs.服务类型最好是成本表中的一列。 You could create views for each type of service if for some reason you want to view your data that way.如果出于某种原因您想以这种方式查看数据,您可以为每种类型的服务创建视图。 I would organize the data like this for easy lookup:我会像这样组织数据以便于查找:

create table ServiceCosts(
  ServiceType char(1),
  MaxDistance decimal(9, 2),
  Cost decimal(9, 2),
  constraint pk_ServiceCosts primary key clustered (ServiceType, MaxDistance)
)

Then you could update the table using an outer apply:然后您可以使用外部应用更新表:

update s
set s.Cost = oa.Cost
from SourceTable s
outer apply (
  select top(1) Cost
  from ServiceCosts sc
  where sc.Weight >= s.Weight
    and sc.Distance >= s.Distance
  order by Cost -- cheapest that fits under weight and distance
) oa

There are a few options you can use, which option is best would depend on the exact criteria of your data.您可以使用几个选项,哪个选项最好取决于您的数据的确切标准。 Does every table have every weight?每张桌子都有不同的重量吗? Every distance?每个距离? What do you do if there is no record meeting your criteria (Cost would be null here)?如果没有符合您标准的记录(此处的成本为空),您会怎么做?

Another option would be to create a function...另一种选择是创建一个函数......

create function GetCost(
    @ServiceType char(1),
    @Weight decimal(9, 2),
    @Distance decimal(9, 2)
) returns decimal(9, 2)
as
begin
  declare @Cost decimal(9, 2) = null;

  if @ServiceType = 'A'
    select top(1) @Cost = case
      when @Distance < 10 then [10 km]
      when @Distance < 20 then [20 km]
      when @Distance < 30 then [30 km]
      else null
    end
    from ServiceATable
    where Weight >= @Weight order by Weight -- least weight at or above limit
  else if -- repeat for each service table

  return @Cost;
end

Then update:然后更新:

update ItemTable
set Cost = GetCost(ServiceType, Weigth, Distance)
where Cost is null; -- only update rows without Cost already

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

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