MySQL:更新SET和WHERE都由一个subselect确定

时间:2013-05-16 17:10:50

标签: mysql sql

我不知道该怎么做..

我有一张这样的表:

account_categories
--------------------
id  | description
--------------------
34  | Home Services
35  | Home Services
36  | Home Services
39  | Home Design
40  | Home Design

我有另一个表(帐户)引用了account_categories.id,它使用了上述所有值。 :/

我想展平account_categories,因此我需要从account_categories中选择一个副本并更新帐户,以便所有重复项都使用所选的一个值。

例如,我需要转变一下:

accounts
---------------------
id  | accountCategory
---------------------
1   | 34
2   | 35
3   | 36
4   | 39
5   | 40

进入这个:

accounts
---------------------
id  | accountCategory
---------------------
1   | 34
2   | 34
3   | 34
4   | 39
5   | 39

我可以从帐户类别中选择ID和不同的描述,如下所示:

SELECT DISTINCT (description), id
FROM crmalpha.account_categories
GROUP BY description

但我想下一步是做这样的事情:

for ( row in ( SELECT DISTINCT (description), id FROM crmalpha.account_categories GROUP BY description ) ) {
    UPDATE crmalpha.accounts SET accountCategory = $row['id'] WHERE accountCategory IN ( SELECT id FROM crmalpha.account_categories WHERE description = $row['description] )
}

原谅for循环和php变量伪代码,我只是试图从逻辑上思考它。我不知道如何在纯SQL中实现这一点。

有什么想法吗?

PS。,之后,我将在accounts_categories中检查并删除帐户表中未使用ID的每一行。

1 个答案:

答案 0 :(得分:3)

当我针对您在上面发布的测试数据进行尝试时,这是有效的。也就是说,在做这样的大规模清理时,我建议先制作一份表格副本。在发出UPDATE之后和发出COMMIT之前检查结果。

以下是查询:

UPDATE Accounts acct
INNER JOIN Account_Categories cat ON acct.AccountCategory = cat.id
INNER JOIN (
  SELECT MIN(id) AS NewID, Description
  FROM Account_Categories
  GROUP BY Description) NewCat ON cat.Description = NewCat.Description
SET acct.AccountCategory = NewCat.NewID

一些解释:

  • 子查询(SELECT MIN(id)...)为每个描述获取一个ID值(最低值)。
  • 第一次加入(至Account_Categories)将每个帐户与其类别相关联,其唯一目的是提供解密。
  • 第二个连接(到子查询)将帐户的现有描述与平展/去除描述及其ID相关联。