3

テーブルに重複したレコードがあります。テーブルから削除できるように、一意の識別子を 1 つだけ識別できる必要があります。

重複があることを知る唯一の方法は列subjectからdescriptionです。そのため、同じ件名と同じ説明が少なくとも 2 つある場合は、1 つを削除して 1 つを残す必要があります。

そのため、重複レコードのリストを取得できましたが、一意の識別子を取得して削除することはできません。

これは、重複レコードを特定するために行ったことです。

SELECT 
    p.accountid, p.subject, p.description, count(*) AS total
FROM
    activities AS p 
WHERE     
    (p.StateCode = 1) AND p.createdon >= getdate()-6
GROUP BY 
    p.accountid, p.subject, p.description
HAVING 
    count(*) > 1
ORDER BY 
    p.accountid

record_id各レコードの一意の識別子を保持する列があります。しかしrecord_id、select ステートメントに追加すると、一意の識別子を重複させることは不可能であるため、結果が得られません。

record_idSQL Server を使用して取得するにはどうすればよいですか?

注: record_id は整数ではなく、「D32B275B-0B2F-4FF6-8089-00000FDA9E8E」のようなものです。

ありがとう

4

4 に答える 4

4

update私が SQL Server で気に入っている優れた機能の 1 つは、 anddeleteステートメントでの CTE の使用です。

重複したレコードを探しており、おそらく最低または最高のいずれかを保持したいと考えていますrecord_id。CTE とウィンドウ関数を使用して、保持するカウントと ID を取得できます。

with todelete as (
    SELECT p.accountid, p.subject, p.description,
           COUNT(*) over (partition by p.accountid, p.subject, p.description) as total,
           MIN(record_id) over (partition by p.accountid, p.subject, p.description) as IdToKeep
    FROM activities AS p 
    WHERE (p.StateCode = 1) AND p.createdon >= getdate()-6
   )
delete from todelete
    where total > 1 and record_id <> IdToKeep;

最後のwhere句は、ロジックを使用して、削除する正しい行を選択するだけです。

追加する必要がありますが、削除されるリストが必要な場合は、同様のクエリを使用できます。

with todelete as (
    SELECT p.accountid, p.subject, p.description,
           COUNT(*) over (partition by p.accountid, p.subject, p.description) as total,
           MIN(record_id) over (partition by p.accountid, p.subject, p.description) as IdToKeep
    FROM activities AS p 
    WHERE (p.StateCode = 1) AND p.createdon >= getdate()-6
   )
select *
from todelete
 where total > 1 and record_id <> IdToKeep;

overfunction は、関数がウィンドウ関数として使用されていることを示します。この考え方は単純です。 句Count(*) over内のフィールドの値が同じであるすべてのレコードの数を返します。partitionすべての行で値を取得する点を除いて、集計関数によく似ています。このクラスの関数は非常に強力です。これらについて詳しく学ぶことをお勧めします。

于 2013-06-05T20:53:49.100 に答える
0

おそらくこのようなものですか?

SELECT max(p.record_id), p.accountid, p.subject, p.description, count(*) AS total
FROM activities AS p 
WHERE (p.StateCode = 1) AND p.createdon >= getdate()-6
GROUP BY p.accountid, p.subject, p.description
HAVING count(*) > 1
ORDER BY p.accountid
于 2013-06-05T20:53:01.497 に答える
0

最初に内部クエリを実行してから、より大きなテーブルに対して結合して、必要なものを取得する必要があるようです。

SELECT ALL
    *
FROM (SELECT p.accountid
  FROM activities AS p
  WHERE p.statecode = 1 AND p.createdon >= getdate()-6
  GROUP BY p.accountid
  HAVING count(*) > 1) AS x
JOIN activities AS a ON x.accountid = a.accountid
ORDER BY p.accountid
于 2013-06-05T20:54:08.940 に答える
0

これを試して:

;with recordsToDelete as (
SELECT 
     recordId
    ,Row_Number() OVER(partition p.subject, p.description) as rowNum
FROM activities AS p 
)

select
*
from recordsToDelete
where rowNum > 1

それが正しいように見える場合は、選択を次のものに置き換えることができます。

delete from recordsToDelete
    where rowNum > 1
于 2013-06-05T21:23:02.850 に答える