删除SQL Server列中的重复数据

时间:2018-11-18 17:00:40

标签: sql sql-server

我正在尝试从名为[dbo].[FactGunSales]的表中删除一些重复的日期,并且该列为[sale_id]。我正在检查下面的代码是否存在重复项,该代码是否有效,然后下面的代码是我遇到的代码,因为它不影响任何行。

-- Detecting Duplicate
SELECT [sale_id], COUNT(*) TotalCount
FROM [dbo].[FactGunSales]
GROUP BY [sale_id]
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC
GO

-- Deleting Duplicate
DELETE FROM [dbo].[FactGunSales]
WHERE [sale_id] NOT IN (SELECT MAX([sale_id])
                        FROM [dbo].[FactGunSales]
                        GROUP BY [sale_id])
GO

任何帮助都会很棒

2 个答案:

答案 0 :(得分:4)

使用not exists

请使用ROW_NUMBER()COUNT(*)。您的代码似乎等同于:

WITH todelete AS (
      SELECT fgs.*, COUNT(*) OVER (PARTITION BY sale_id) as cnt
      FROM [dbo].[FactGunSales] fgs
     )
DELETE FROM to_delete
WHERE cnt > 1;

不过,通常情况下,您不想删除所有 个重复项。您想保留其中之一。为此,请使用ROW_NUMBER()

WITH todelete AS (
      SELECT fgs.*, ROW_NUMBER() OVER (PARTITION BY sale_id ORDER BY sale_id) as seqnum
      FROM [dbo].[FactGunSales] fgs
     )
DELETE FROM to_delete
WHERE seqnum > 1;

您的查询没有提供关于要保留哪个行的指示。此版本保留任意行。您可以通过更改ORDER BY子句来保持最新或最旧或最大或最小或任何其他值。

您的版本不会删除任何内容,因为sale_id的至少一个值为NULL。如果子查询返回的 any 值为NULL,则WHERE会过滤掉所有行。通常,我强烈建议改用NOT EXISTS,但为此目的,更新CTE更具意义。

答案 1 :(得分:0)

您可以考虑使用cte并根据sale_id对记录进行排名,因此任何重复的sale_id将具有rank = 2,3,4等。之后,您需要删除<> rank的条目= 1

(defparameter *ht-2* (make-hash-table :test 'equal))
(setf (gethash *key* *ht-2*) 20)
*ht-2*
==> #S(HASH-TABLE :TEST FASTHASH-EQUAL ((42) . 20))
(gethash *key* *ht-2*)
==> 20; T
(setf (car *key*) 7)            ; **visible modification**!
(gethash '(7) *ht-2*)
==> unspecified!
(gethash *key* *ht-2*)
==> unspecified!
(setf (car *key*) 42)           ; restore key
(gethash '(42) *ht-2*)
==> unspecified!
(gethash *key* *ht-2*)
==> unspecified!