0

我有以下架构:

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

4

3 回答 3

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 和子查询;)


显然你不能从你正在更新的表中选择 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)
于 2011-06-27T09:09:07.673 回答
0

Oswald 关于行的排序(或缺少)的评论非常重要。您没有任何保证,period,从该表中选择的未排序行将按照您期望的顺序。这意味着,除非您每次都指定现有的表顺序,否则即使这不能反映现实,也可以将事物标记为“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"

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

如果您坚持在数据库中执行此操作,则可以这样编写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
于 2011-06-27T22:38:03.100 回答
0

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

于 2011-06-27T09:08:35.320 回答