【问题标题】:Update Table based of another with one to many relationship. No cursors基于另一个具有一对多关系的更新表。没有游标
【发布时间】:2013-09-26 18:05:32
【问题描述】:

我有这两个表和 SQL Server 中的一些示例数据。

Rules 表只是Inventory 表的SELECT DISTINCT (DataSource_Id, LocationCode, WarehouseCode, WarehouseName, MTO_Regional)

我想根据Inventory 中的MTO_MTS 值更新Rules 表中的SS_Value 列,其中/如果三个“SSIn...”列中的任何一个都有值。

示例: Rules 表中的第一条记录将获取 Inventory 表中的第一个 MTO_MTS 值,该值基于 (DataSource_Id, LocationCode, WarehouseCode, WarehouseName, MTO_MTSRegional) 匹配并且具有一个 'SSIn ...' 不为 0 的列。

因此它可以抓取 Inventory 中的前两条记录中的任何一条,因为这 5 列匹配,并且至少有一个 SSIn.. 列不为零

到目前为止我所做的尝试:

我尝试过使用游标,但有数百万条记录,因此无法处理。我正在尝试构建一个更新语句,但无法弄清楚语法。

UPDATE Rules r
SET SS_Value = (SELECT TOP(1) MTO_MTS FROM Inventory ip
                WHERE r.DataSource_Id = ip.DataSource_Id
                AND r.LocationCode = ip.LocationCode 
                AND r.WarehouseCode = ip.WarehouseCode
                AND r.WarehouseName = ip.WarehouseName
                AND r.MTO_MTSRegional = ip.MTO_MTSRegional 
                (ip.SafetyStockInKLG <> 0 OR ip.SafetyStockInLTR <> 0 OR ip.SafetyStockInUnits <> 0)

我认为这个一般想法中的某些内容可能有效,但我无法正确使用语法。

我也试过这样的语法:

UPDATE Rules
SET ip.SS_Value
FROM InventoryProduction ip 
INNER JOIN Rules

我在查询中的表范围方面遇到了问题,并从正在更新的行中获取值以应用于 WHERE 子句。

【问题讨论】:

  • 那 3 行中的哪一行是第一行?,您如何订购它们? (请不要说“因为它是第一个”,我们需要一种订购方式)
  • 我不确定我是否 100% 理解您的问题。但是,据我所知,Inventory 表没有固定的顺序,只是每当该记录插入数据库时​​,就会有一个递增的 Id 列。在符合条件的行中,您抓取哪一行并不重要。如果这不能回答您的问题,请告诉我,我可以尝试更好地理解。
  • “Rules 表中的第一条记录将获取 Inventory 表中的 first MTO_MTS 值”,那么,哪一个是第一行?,有 3 个选项
  • 我的意思是,Rules 表中的第一条记录将抓取任何符合条件的记录。因此它可以抓取 Inventory 中的前两条记录中的任何一条,因为这 5 列匹配,并且 SSin.. 中至少有一个非零

标签: sql sql-server sql-server-2008 sql-update


【解决方案1】:

“第一个 MTO_MTS 值”是什么意思?

这是一种方式,写为 SELECT,假设“first”表示“minimum”。使用它来验证它是否提供了你想要的,然后变成一个更新:

SELECT
 Rules.DataSourceID,
 Rules.LocationCode,
 Rules.WarehouseCode,
 Rules.WarehouseName,
 Rules.MTO_MTSRegional,
 SS_Value = MIN(Inventory.MTO_MTS)
FROM Rules
INNER JOIN Inventory
 ON Rules.DataSource_Id = Inventory.DataSource_Id
  AND Rules.LocationCode = Inventory.LocationCode 
  AND Rules.WarehouseCode = Inventory.WarehouseCode
  AND Rules.WarehouseName = Inventory.WarehouseName
  AND Rules.MTO_MTSRegional = Inventory.MTO_MTSRegional 
  (Inventory.SafetyStockInKLG <> 0 OR Inventory.SafetyStockInLTR <> 0 OR Inventory.SafetyStockInUnits <> 0)
GROUP BY
 Rules.DataSourceID,
 Rules.LocationCode,
 Rules.WarehouseCode,
 Rules.WarehouseName,
 Rules.MTO_MTSRegional

【讨论】:

  • First 可能不是最好的词......我抓取哪条记录并不重要,如果它们符合标准,它们应该都是相同的。因此,只要所有匹配项,我都可以从结果集中获取任何内容。
【解决方案2】:

第一步只选择一个可用于更新的行。您可以在 ROW_NUMBER() 的 ORDER BY 中添加更多列。它改变了 cl 输出。我希望它有效。

with cl
as
(SELECT MTO_MTS, ip.DataSource_Id, ip.LocationCode, ip.WarehouseCode, ip.WarehouseName,  ip.MTO_MTSRegional, ROW_NUMBER() OVER(PARTITION BY MTO_MTS ORDER BY DataSource_Id) rn
FROM Inventory ip inner join Rules r on
r.DataSource_Id = ip.DataSource_Id
AND r.LocationCode = ip.LocationCode 
AND r.WarehouseCode = ip.WarehouseCode
AND r.WarehouseName = ip.WarehouseName
AND r.MTO_MTSRegional = ip.MTO_MTSRegional 
where  (ip.SafetyStockInKLG <> 0 OR ip.SafetyStockInLTR <> 0 OR ip.SafetyStockInUnits <> 0)
)

UPDATE r
SET SS_Value = cl.MTO_MTS
from Rules r inner join cl on r.DataSource_Id = cl.DataSource_Id
AND r.LocationCode = cl.LocationCode 
AND r.WarehouseCode = cl.WarehouseCode
AND r.WarehouseName = cl.WarehouseName
AND r.MTO_MTSRegional = cl.MTO_MTSRegional 
where cl.rn = 1

【讨论】:

    最近更新 更多