【问题标题】:SQL Update throwing error at JOIN subquerySQL 更新在 JOIN 子查询中抛出错误
【发布时间】:2017-03-02 15:27:27
【问题描述】:

我有一个帐户表,其中有一行用于 role_id。我有另一个名为组织组的表,其中包含与组织关联的组,这个表有一个 ID 和一个名称列。我有第三个名为 account_group 的表,它有两列 account_id 和 group_id 将两者映射在一起。

现在我想检查帐户的组,并根据组的名称更新此帐户的角色 id 值。

我设法想到的查询:

    UPDATE account 
SET account.role_id = (CASE WHEN organisation_group.name = "Social Worker" THEN 50
                            WHEN organisation_group.name = "Foster Carer" THEN 26
                       END)
    WHERE organisation_group.name in 
    (SELECT organisation_group.name FROM organisation_group 
INNER JOIN account_group ON organisation_group.id = account_group.group_id 
WHERE organisation_id = 11 GROUP BY organisation_group.name);

这会引发以下错误 Unknown column 'organisation_group.name' in 'IN/ALL/ANY subquery' 。我不擅长 SQL,但我需要这个更新。任何想法如何执行此操作。

50 和 26 是我要使用的角色 ID。

更新 1(更清晰的解释)

我有一个包含 [id,username,name,role_id,organisation_id] 列的帐户表。

我需要编辑 account.role_id 列。我需要做的是:

  1. 检查帐户的组名。

这些组位于名为 organization_group 的表中。该表有三列 [id,organisation_id,name]。

要将帐户与组映射,我有一个名为 account_group 的表,其中包含三列 [id. account_id , group_id]。

2- 根据组名,我需要更新 account.role_id 以在(组名 = 角色名)时具有角色 ID。

角色存储在名为 organization_role 的表中,该表包含 [id,name,organisation_id] 列。

【问题讨论】:

  • 您不能在子查询之外访问organisation_group 表。
  • 一些示例数据或更好地描述您正在尝试做的事情会有所帮助。
  • 您的查询没有意义。您正在按organisation_group.name 对子查询进行分组。因此,您将失去与 account 表的任何关系。
  • @PaulSpiegel 我承认这可能没有意义,因为我在 SQL 方面不是那么好,这是我试图解决我的问题。感谢您查看问题,我已经添加了我想要做什么的额外描述。
  • 看起来您的查询与您的要求无关 :-)。你的要求有点奇怪。尝试用示例数据来解释。

标签: mysql sql-update inner-join


【解决方案1】:

首先在您的 where 条件中,您指的是在顶层不可见的 table.column WHERE organisation_group.name 你可能需要account.name 其次,一个建议,你没有聚合函数 i 子查询,所以如果你需要不同的值,请使用 distinct 子句

UPDATE account 
SET account.role_id = (CASE WHEN organisation_group.name = "Social Worker" THEN 50
                            WHEN organisation_group.name = "Foster Carer" THEN 26
                       END)
WHERE account.name in 
    ( SELECT distinct organisation_group.name FROM organisation_group 
      INNER JOIN account_group ON organisation_group.id = account_group.group_id 
      WHERE organisation_id = 11 
     );

但是 如果我理解你的加入规则,你应该以这种方式加入

UPDATE account 
INNER JOIN account_group on account_group.account_id = account.id
INNER JOIN organisation_group on organisation_group.id = account_group.group_id 
SET account.role_id = (CASE WHEN organisation_group.name = "Social Worker" THEN 50
                        WHEN organisation_group.name = "Foster Carer" THEN 26
                   END)
WHERE organisation_group.id = 11

【讨论】:

  • 您附加的脚本仍然会引发相同的错误,因为正如您所说,我们无法从子查询外部访问 organization_group.name。不知道如何解决这个问题..有什么想法吗? .. 谢谢!
  • 你需要什么条件..? .必须涉及账户表的哪一列?如何 .. ?试着解释一下,这样我就可以评估了..
  • 我已经更新了 asnwer,添加了一个已加入的更新...希望是您所需要的 .. 或者至少引导您走上正确的道路 ..
  • 非常感谢,我现在就测试一下。为了以防万一,我还更新了问题以包含更清晰的解释。
  • 它与快速编辑完美配合。我希望你不介意我编辑答案。我只是把它做对了,所以我可以接受它作为正确的答案。非常感谢您的帮助。
【解决方案2】:

这是我使用的技术。我没有开始尝试编写多表 UPDATE 语句,而是通过编写 SELECT 语句来开始该过程。

SELECT 语句的目标是返回我要更新的行(至少是该行的主键/唯一键/标识符),以及要更新的列(将要更新的当前值)替换。)除此之外,我还返回了我要分配给列的新值。

我可以调整和使用那个 SELECT 语句,让它准确地返回我想要的行。我可以验证将要分配的新值。而且我可以做到所有这些,而不会破坏数据库并更新错误的行。

一旦我验证了 SELECT 语句,通常可以直接将其转换为 UPDATE 语句。 (在某些情况下,我将不得不使用 SELECT 语句并用括号括起来并将其用作内联视图。)


我们可以从我们要更新的表开始。

SELECT a.id
     , a.group_name
     , a.role_id
  FROM account a
 ORDER BY a.id

添加加入account_group

SELECT a.id
     , a.group_name
     , a.role_id
     , g.group_id
  FROM account a
  JOIN account_group g
    ON g.account_id = a.id
 ORDER BY a.id

(这仍然返回我们想要返回的所有行吗?还是更多行?如果我们要匹配多行,那么我们实际上想要匹配哪一行......是基数吗?)

然后将join添加到organisation_group

SELECT a.id
     , a.group_name
     , a.role_id
     , g.group_id
     , o.name
  FROM account a
  JOIN account_group g
    ON g.account_id = a.id
  JOIN organisation_group o
    ON o.id = g.group_id
 ORDER BY a.id

是否返回了正确的行?然后我们可以添加表达式以将 role_id 派生到 SELECT 列表中。

SELECT a.id
     , a.group_name
     , a.role_id
     , g.group_id
     , o.name

     , CASE o.name 
       WHEN 'Social Worker' THEN 50
       WHEN 'Foster Care'   THEN 26
       ELSE NULL
       END AS new_role_id

  FROM account a
  JOIN account_group g
    ON g.account_id = a.id
  JOIN organisation_group o
    ON o.id = g.group_id
 ORDER BY a.id

group_name 中是否有任何 NULL 值或 group_name 的值不匹配? new_role_id 列是否包含我们要分配的值,是否对每一行都正确?是否有任何我们不想更新的行被返回?我们是否想将除 'Social Worker' 和 'Foster Care' 以外的名字的 role_id 设置为 NULL,还是保持原样? (通过将 NULL 替换为 a.role_id)?

一旦我们的 SELECT 语句工作,将其转换为 UPDATE。

我们只需将SELECT ... FROM 替换为UPDATE 关键字,并在WHERE 子句之前添加一个SET 子句(或者在这种情况下,在ORDER BY 子句之前。)

在本例中,我们可以将new_role_id 表达式分配给role_id 列。

UPDATE account a
  JOIN account_group g
    ON g.account_id = a.id
  JOIN organisation_group o
    ON o.id = g.group_id
   SET a.role_id
     = CASE o.name 
       WHEN 'Social Worker' THEN 50
       WHEN 'Foster Care'   THEN 26
       ELSE NULL
       END
 ORDER BY a.id

这是我用来构建多表更新语句的方法。我不够聪明,无法开始编写 UPDATE 语句。我使用逐步改进来构建 SELECT 语句,因为我想确定我知道该语句将要做什么。通过检查 SELECT 返回的结果,我可以进行验证。在我用 UPDATE 修饰表之前。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-24
    • 2016-01-07
    • 2016-07-10
    • 1970-01-01
    • 2023-03-15
    • 2019-09-21
    • 2014-07-27
    • 2012-07-16
    相关资源
    最近更新 更多