【问题标题】:Update subsequent duplicate field values in mysql更新mysql中后续重复的字段值
【发布时间】:2011-09-23 08:19:38
【问题描述】:

我有以下架构:

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 & 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' 进行更新

【问题讨论】:

  • 感谢安德烈的回复。正如您所说,架构是正确的,但是具有相同描述的多行的问题来自我必须导入数据的方式。数据最初采用 Filemaker (4!) 格式。每个 'order_ref' 都有描述 |价格 |数量,但不是每个 order_ref 有 1 行,而是格式 order_ref |描述 |值 1 |价格 1 |值 2 |价格 2. 此外,每个对应的描述仅由“随机”换行符分隔,因此不可能将描述与每个“行”分开。
  • 我复制了描述,这样至少我们还有可用的历史数据。展望未来,每个描述都匹配它自己的价值 |价格应该是架构。排序应该在这里起作用,因为它们在导入之前已正确排序,因此第一个描述(按 id)将是要保留的。

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


【解决方案1】:

如果这是一次性的事情,那么性能并不是什么大问题。您可以对 LIMIT 为 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)

【讨论】:

  • Martinho,这正是我想要做的,因为我想要保留描述的第一个“事件”。有什么想法可以重写查询以解决 LIMIT 问题(更新问题)?
  • 哎呀,现在,这是个问题!不确定,但也许你可以巧妙地使用 MIN 来解决这个问题。我会看看我能做些什么并更新我的答案。
  • 我更新了我的答案(另外,请注意我将 t.description &lt;&gt; description 更改为 t.description = description,这是一个可能是灾难性的错字!在运行更新之前务必仔细检查查询!)
  • @Jeepstone:该死。新编辑。让我们看看它现在是否还能反击:)
  • ;o) 刚刚影响了第一行并将所有其他行更新为 -AS ABOVE- 哎呀!
【解决方案2】:

关系数据库没有后续的概念。表中的记录没有任何特定的顺序。如果您未在 SELECT 查询中指定顺序,则必须假设记录是以您不期望的顺序检索的。

【讨论】:

    【解决方案3】:

    Oswald 关于行排序(或缺少排序)的评论非常重要。您没有任何保证,句号,从该表中选择的未排序行将按照您期望的顺序排列。这意味着除非您每次指定现有的表格顺序,否则即使这不反映现实,也可能会标记为“AS ABOVE”。此外,目前提供的解决方案都不能正确处理任何乱序记录。
    总的来说,这听起来更像是数据库设计问题(特别是规范化问题),而不是查询问题。
    理想情况下,描述将被提取到一些主数据表(连同必要的 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 问题,由您输出要显示的行的任何程序处理(而不是直接在数据库中)。

    如果您坚持在数据库中执行此操作,您可以这样写 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
    

    【讨论】:

      猜你喜欢
      • 2016-01-17
      • 1970-01-01
      • 2018-04-03
      • 2011-02-06
      • 2013-03-18
      • 2010-12-21
      • 2017-03-11
      • 1970-01-01
      相关资源
      最近更新 更多