更新mysql中的后续重复字段值

时间:2011-06-27 08:52:07

标签: mysql sql sql-update mysql-error-1093

我有以下架构:

id | order_ref | description | price

目前我有以下重复问题:

1 | 34567 | This is the description | 19.99
2 | 34567 | This is the description | 13.99

这是由于我导入的数据,每个项目的描述都是重复的。有没有办法可以保留第一行,然后将后续(最多约20行)的描述更新为'AS ABOVE'?

1 | 34567 | This is the description | 19.99
2 | 34567 | - AS ABOVE - | 13.99

由于

-------修订版

UPDATE documents_orders_breakdown
SET `desc` = '- AS ABOVE -'
WHERE NOT id IN (SELECT id
             FROM documents_orders_breakdown AS D
             WHERE D.`desc` <> `desc`
             ORDER BY D.id
             LIMIT 1)

但这会返回[Err] 1235 - 这个版本的MySQL还不支持'LIMIT&amp; IN / ALL / ANY / SOME子查询'

--------修订版

UPDATE documents_orders_breakdown
SET `desc` = '- AS ABOVE -'
WHERE NOT id IN (SELECT MIN(id)
                 FROM documents_orders_breakdown AS t
                 WHERE t.`desc` = `desc`)

现在返回[Err] 1093 - 您无法在FROM子句中为更新指定目标表'documents_orders_breakdown'

3 个答案:

答案 0 :(得分:1)

如果这是一次性的事情,性能不是一个大问题。您可以对SELECT值为1的SELECT未返回的所有记录运行UPDATE。

UPDATE the_table
SET description = '- AS ABOVE -'
WHERE NOT id IN (SELECT id
                 FROM the_table t
                 WHERE t.description = the_table.description
                 ORDER BY t.id
                 LIMIT 1)

此查询假定您要保留id为第一位的记录的描述(因此为ORDER BY)。


由于您无法在子查询中使用LIMIT,因此可以使用聚合函数MIN来解决这个问题:

UPDATE the_table
SET description = '- AS ABOVE -'
WHERE NOT id IN (SELECT MIN(id)
                 FROM the_table t
                 WHERE t.description = the_table.description)

(我们希望您可以混合使用MIN和子查询;)


显然是you can't SELECT from the table you're UPDATEing in MySQL。解决方法是使用隐式临时表。这对性能不利,但是,再次,鉴于这是一次性的事情,这不是一个大问题。

UPDATE the_table
SET description = '- AS ABOVE -'
WHERE NOT id IN (SELECT m FROM (SELECT MIN(id) AS m
                 FROM the_table t
                 WHERE t.description = the_table.description) AS temp)

答案 1 :(得分:0)

关系日期基础没有后续的概念。表中的记录没有任何特定顺序。如果您未在SELECT查询中指定订单,则必须假定按照您不期望的顺序检索记录。

答案 2 :(得分:0)

Oswald关于行的排序(或缺少)的评论非常重要。您没有受限,期间,从此表中选择的未排序行将按您期望的顺序排列。这意味着除非您每次都按照表格顺序指定现有,否则即使这不能反映现实情况,也可以标记为“如上所述”。此外,到目前为止,所提供的解决方案都没有适当地处理任何无序记录 总的来说,这听起来更像是数据库设计问题(特别是规范化问题),而不是查询问题 理想情况下,描述将被提取到一些主数据表(以及必要的ID)。然后,关于要使用的描述的选择留在'SELECT'运行时。这样做的另一个好处是可以使“AS ABOVE”对订购的变化安全。

因此,假设order_ref列的每个实例都应该有不同的描述(除非'AS ABOVE'位),表格可以重构如下:

id | order_ref | price 
======================= 
 1 | 34567     | 19.99  
 2 | 34567     | 13.99  

order_ref_fk | description  
==========================================
34567        | "This is the description"

此时,您正常加入描述表。显示不同的描述通常是 display 问题,无论是由输出要显示的行(而不是直接在数据库中)的任何程序处理。

如果你坚持在in-db中这样做,你可以用这种方式编写SELECT

SELECT Orders.id, Orders.order_ref, Orders.price,
       COALESCE(Dsc.description, 'AS ABOVE')
FROM Orders
LEFT JOIN (Description
           JOIN (SELECT order_ref, MIN(id) AS id
                 FROM Orders
                 GROUP BY order_ref) Ord
             ON Ord.order_ref = Description.order_ref_fk) Dsc
        ON Dsc.order_ref_fk = Orders.order_ref
           AND Dsc.id = Orders.id
ORDER BY Orders.order_ref, Orders.id