📅  最后修改于: 2023-12-03 15:06:38.694000             🧑  作者: Mango
在处理数据库时,我们有时会遇到需要从表中删除重复行的情况。SQL提供了几种方法来实现这个目的。
使用DISTINCT关键字可以返回唯一的行,从而避免重复行的问题。这种方法适用于只有部分列有重复值的情况。
例如,假设我们有一个名为customers
的表,其中包含以下列:id
、name
和email
。如果我们想要删除重复的name
和email
组合,可以使用以下SQL查询:
DELETE FROM customers
WHERE id NOT IN (
SELECT MIN(id)
FROM customers
GROUP BY name, email);
上述查询使用子查询和GROUP BY语句查找具有重复name
和email
的行,然后使用DELETE语句删除除了具有最小id
值的行之外的行。
ROW_NUMBER()函数可以为查询结果中的每一行分配一个唯一的序号。这种方法可以更灵活地处理重复行的情况。
例如,使用上述customers
表,如果我们想要删除具有重复name
和email
组合的行,可以使用以下SQL查询:
WITH cte AS (
SELECT ROW_NUMBER() OVER(
PARTITION BY name, email ORDER BY id) AS rownum
FROM customers)
DELETE FROM cte WHERE rownum > 1;
上述查询使用了CTE(公用表表达式)和ROW_NUMBER()函数来为具有重复name
和email
组合的行分配一个唯一的序号,并使用DELETE语句删除具有序号大于1的行。
如果表中包含大量重复行,使用临时表可能是更高效的方法。
例如,假设我们有一个名为sales
的表,其中包含以下列:id
、order_number
、customer_name
和order_total
。我们想要删除具有相同order_number
和customer_name
的行,但保留具有最大order_total
值的行。可以使用以下SQL查询:
CREATE TABLE #temp_sales (
id INT PRIMARY KEY,
order_number VARCHAR(20),
customer_name VARCHAR(50),
order_total MONEY);
INSERT INTO #temp_sales (id, order_number, customer_name, order_total)
SELECT id, order_number, customer_name, order_total
FROM sales;
DELETE FROM sales;
INSERT INTO sales (id, order_number, customer_name, order_total)
SELECT t.id, t.order_number, t.customer_name, t.order_total
FROM (
SELECT id, order_number, customer_name, order_total,
ROW_NUMBER() OVER(
PARTITION BY order_number, customer_name
ORDER BY order_total DESC) AS rownum
FROM #temp_sales) t
WHERE t.rownum = 1;
DROP TABLE #temp_sales;
上述查询使用了临时表和ROW_NUMBER()函数来查找具有相同order_number
和customer_name
的行,然后使用DELETE语句删除数量多于1的行,并使用INSERT语句将具有最大order_total
值的行重新插入sales
表中。
总之,在SQL中有多种方法可以从表中删除重复行,可以根据具体情况选择最合适的方法。