【问题标题】:How to write a loop as a SQL query efficiently如何有效地将循环编写为 SQL 查询
【发布时间】:2014-04-17 06:35:44
【问题描述】:

如何将以下算法编码为 SQL 查询(abc 是我数据库中的表)

for all a:
case c.column=0
set a.columnname+=b.column1*b.column2
case c.column=1
...

earlier i solved a similar problem by:                          
UPDATE a 
set
a.column= (select SUM(column1) from b where a.column2=b.column2)   

但由于 in 是对两列的乘积求和,我认为我不能这样做。 真正的问题还在于 a 与 c 的一对多关系。

关系:

一对多 b.

b 一对一 c

假设 A 是公司数据表,B 是员工数据表,C 告诉我们员工是男性还是女性(只是一个例子,并不是我的问题)。现在我需要计算每个公司给每个员工的总工资,并将其存储在公司表的一个字段中。可以说我根据员工的性别以不同的方式计算这个。现在又有数百家公司,每家公司都有数千名员工。

【问题讨论】:

  • 您可以查看游标,但使用错误,它们很烂。为什么你需要在 sql 中循环?我过去曾多次想过同样的问题,并且通常已经向我展示了一种使用单行选择或更新语句的方法。
  • 您的表是如何相互关联的?剩下的逻辑是什么?有统一性吗?
  • 您的表格是否相互关联?你能用简单的英语而不是伪代码说明你想要做什么吗?
  • @user2197558 从过程语言到基于集合的语言的转换几乎从来没有那么简单。

标签: sql


【解决方案1】:

您可能希望将其分解为一系列查询,将 case 语句中的“案例”作为不同的 WHERE 子句:

UPDATE <thing>
SET .......
FROM a,b c
INNER JOIN .......
WHERE c.column=0;


UPDATE <thing>
SET .......
FROM a,b c
INNER JOIN .......
WHERE c.column=1;

有关语法类型的示例,请参见这些:

【讨论】:

  • 由于 a 和 b 之间存在一对多关系,因此连接会填充太多行。
  • hm,您可能还想创建一些带有要更新的值的临时表,以避免一对多的问题。我认为另一个答案中的 Rinze Smits 有一个解决方案,这一切都在一个查询中。
【解决方案2】:

如果您在每种情况下都更新columnname,那么您不需要循环:

UPDATE a
SET columnname = 
   CASE WHEN c.column=0
      THEN columnname + b.column1*b.column2
   CASE WHEN c.column=1
      THEN ...

否则,使用不同 WHERE 子句的多个 UPDATE 会更干净

根据您的更新和评论,这样的事情可能会起作用:

UPDATE a 
set a.column = 
(SELECT 
 SUM(
     CASE WHEN c.EmployeeGender = 0
            THEN b.column1*b.column2
          WHEN c.EmployeeGender = 1
            THEN ... 
          ELSE 
     END
     )
 FROM b 
 INNER JOIN c
    ON b.EmployeeID = c.EmployeeID
 WHERE a.column2=b.column2) 

【讨论】:

  • 由于 a 和 b 之间的一对多关系,我实际上正在尝试使用连接来解决问题。它填充了太多行。
  • 如果你不能加入他们,你还能如何将ab 联系起来?
  • 我已更新以展示我在前面的示例中是如何做到的
【解决方案3】:

要减少集合,您可以使用 GROUP BY 和聚合函数,例如 SUM。 对于 A 中的每条记录,您希望获得 B 和 C 中所有相关记录的某个函数的总和。

首先,我们将创建一个SELECT 声明以确保我们获得正确的数据。这看起来像:

SELECT 
  a.id,
  SUM(CASE WHEN c.[column]=0 THEN b.column1 * b.column2 ELSE 0 END) +
    SUM(CASE WHEN c.[column]=1 THEN b.column1 + b.column2 ELSE 0 END) AS new_value
FROM a
INNER JOIN b ON a.id = b.a_id
INNER JOIN c ON b.id = c.b_id
GROUP BY a.id --and all other columns from A that you select/update, making sure it contains at least the columns required to select a unique record from a.

要将其转换为更新语句,您可以对常规表 A 进行 1:1 连接:

UPDATE updated_a
  SET columnname = new_value
  FROM a AS updated_a INNER JOIN
   (SELECT 
  a.id,
  SUM(CASE WHEN c.[column]=0 THEN b.column1 * b.column2 ELSE 0 END) +
    SUM(CASE WHEN c.[column]=1 THEN b.column1 + b.column2 ELSE 0 END) AS new_value
FROM a
INNER JOIN b ON a.id = b.a_id
INNER JOIN c ON b.id = c.b_id
GROUP BY a.id) AS calculation ON updated_a.id = calculation.id;

http://sqlfiddle.com/#!6/2dffa/14

【讨论】:

    猜你喜欢
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    • 2021-01-15
    相关资源
    最近更新 更多