使用连接表的 AVG 进行 SQL 更新

Posted

技术标签:

【中文标题】使用连接表的 AVG 进行 SQL 更新【英文标题】:SQL Update with AVG of Joined Tables 【发布时间】:2020-02-15 10:59:09 【问题描述】:

我正在尝试通过计算订单日期和库存收货日期之间的差异来更新表格中的供应商提前期....

UPDATE cr_accs 
SET    cr_accs.leadtime = Avg(Datediff(day, purchord_hdr.orderdate, 
                                     stock_trans.transdate)) 
FROM   stock_items 
       INNER JOIN stock_trans 
               ON stock_trans.stockcode = stock_items.stockcode 
       INNER JOIN purchord_hdr 
               ON purchord_hdr.seqno = stock_trans.ref1 
WHERE   cr_accs.accno = purchord_hdr.accno 
       AND stock_trans.location = 1 
       AND stock_trans.ref2 = 'RECEIPT'
       AND purchord_hdr.orderdate >= Dateadd(day, Datediff(day, 0, Getdate()),-730) 
       AND stock_items.isactive = 'Y' 
       AND stock_items.bincode NOT IN ( 'OIO', 'CON' ) 

但是我得到一个错误

聚合可能不会出现在 UPDATE 语句的集合列表中

我见过其他解决方案,您可以将查询更改为:

UPDATE cr_accs 
SET    cr_accs.leadtime = h.calc_lead_time
FROM   (SELECT AVG(DATEDIFF(day, purchord_hdr.orderdate, stock_trans.transdate)) AS calc_lead_time  
        FROM stock_items 
       INNER JOIN stock_trans 
               ON stock_trans.stockcode = stock_items.stockcode 
       INNER JOIN purchord_hdr 
               ON purchord_hdr.seqno = stock_trans.ref1  
       INNER JOIN cr_accs 
               ON cr_accs.accno = purchord_hdr.accno 
WHERE   cr_accs.accno = purchord_hdr.accno  
       AND stock_trans.location = 1 
       AND stock_trans.ref2 = 'RECEIPT' 
       AND purchord_hdr.orderdate >= Dateadd(day, Datediff(day, 0, Getdate()),-730) 
       AND stock_items.isactive = 'Y' 
       AND stock_items.bincode NOT IN ( 'OIO', 'CON' ) ) h

但这不是我的解决方案,因为它没有定义每个供应商的交货时间都是独一无二的...... 指出每个供应商都由 cr_accs.accno 标识可能会有所帮助

有什么想法吗?

【问题讨论】:

您使用的是哪种 DBMS 产品? “SQL”只是一种查询语言,而不是特定数据库产品的名称(在标准 SQL 中,UPDATE 命令没有 FROM 子句)。 Why should I tag my DBMS 【参考方案1】:

您还可以使用相关子查询来做您想做的事情,这可能是您想要做的事情:

UPDATE cr_accs 
    SET cr_accs.leadtime =
         (SELECT AVG(DATEDIFF(day, p.orderdate, st.transdate)) AS calc_lead_time  
          FROM stock_items si JOIN
               stock_trans st
               ON st.stockcode = si.stockcode JOIN
               purchord_hdr p
               ON p.seqno = st.ref1  
          WHERE cr_accs.accno = p.accno  AND
                st.location = 1 AND
                st.ref2 = 'RECEIPT' AND
                p.orderdate >= Dateadd(day, Datediff(day, 0, Getdate()), -730) AND
                si.isactive = 'Y' AND
                si.bincode NOT IN ( 'OIO', 'CON' )
         );

我引入了表别名,以便查询更易于编写和阅读。

SQL Server 还使您能够使用APPLY 表达这一点:

UPDATE a 
    SET a.leadtime = p.calc_lead_time
    FROM cr_accs a CROSS APPLY
         (SELECT AVG(DATEDIFF(day, p.orderdate, st.transdate)) AS calc_lead_time  
          FROM stock_items si JOIN
               stock_trans st
               ON st.stockcode = si.stockcode JOIN
               purchord_hdr p
               ON p.seqno = st.ref1  
          WHERE a.accno = p.accno  AND
                st.location = 1 AND
                st.ref2 = 'RECEIPT' AND
                p.orderdate >= Dateadd(day, Datediff(day, 0, Getdate()), -730) AND
                si.isactive = 'Y' AND
                si.bincode NOT IN ( 'OIO', 'CON' )
         ) p;

【讨论】:

谢谢 Gordon Linoff - 这确实有效,谢谢 :-) 您的答案会更新表格中的每个供应商交货时间,无论是否在两年内(> = 730 天)内进行了任何购买 - 在那里没有采购,交货时间为空......(正确)。 @forpas 解决方案也适用 - 但是只更新已经购买的供应商(902 行受影响,两个查询之间有 235 行)。因此,两者都是正确的,具体取决于您想要的结果。【参考方案2】:

尝试将表连接到查询:

UPDATE c
SET c.leadtime = h.calc_lead_time
FROM cr_accs c 
INNER JOIN (
  SELECT purchord_hdr.accno,
    AVG(DATEDIFF(day, purchord_hdr.orderdate, stock_trans.transdate)) AS calc_lead_time  
  FROM stock_items 
  INNER JOIN stock_trans ON stock_trans.stockcode = stock_items.stockcode 
  INNER JOIN purchord_hdr ON purchord_hdr.seqno = stock_trans.ref1  
  WHERE      stock_trans.location = 1 
         AND stock_trans.ref2 = 'RECEIPT' 
         AND purchord_hdr.orderdate >= Dateadd(day, Datediff(day, 0, Getdate()),-730) 
         AND stock_items.isactive = 'Y' 
         AND stock_items.bincode NOT IN ('OIO', 'CON') 
  GROUP BY purchord_hdr.accno
) h ON h.accno = c.accno

我假设(根据您的代码和错误消息)您正在使用 SQL Server。

【讨论】:

以上是关于使用连接表的 AVG 进行 SQL 更新的主要内容,如果未能解决你的问题,请参考以下文章

Postgres 使用跨 2 个表的内部连接进行更新?

使用连接的 SQL 更新查询

使用连接的 SQL 更新查询

使用连接的 SQL 更新查询

使用连接的SQL更新查询

在 SQL Server 2005 express 中使用连接