2

Candidate duplicates のリストを作成するためのこのクエリは非常に簡単です。

SELECT Count(*), Can_FName, Can_HPhone, Can_EMail
FROM Can 
GROUP BY Can_FName, Can_HPhone, Can_EMail
HAVING Count(*) > 1

しかし、チェックしたい実際のルールが FName と (HPhone OR Email) である場合、GROUP BY を調整してこれを処理するにはどうすればよいでしょうか?

ここで UNION SELECT を実行することになると確信しています (つまり、一方に FName、HPhone を実行し、もう一方に FName、EMail を実行して結果を結合します)。それを行う方法。

よろしくお願いします。

メイン州のスコット

4

7 に答える 7

0

これを試して:

SELECT Can_FName, COUNT(*)
FROM (
SELECT 
rank() over(partition by Can_FName order by  Can_FName,Can_HPhone) rnk_p,
rank() over(partition by Can_FName order by  Can_FName,Can_EMail) rnk_m,
Can_FName
FROM Can
) X
WHERE rnk_p=1 or rnk_m =1
GROUP BY Can_FName
HAVING COUNT(*)>1
于 2009-07-02T19:47:46.903 に答える
0

これらの答えはどれも正しくありません。Quassnoi のアプローチは適切ですが、"qo.id > dup.id" および "di.chainid < do.chainid" という式に致命的な欠陥が 1 つあります。ID による比較です! ID 固有の順序に依存するため、これは常に悪い習慣です。ID に暗黙的な意味を与えることは絶対に避けてください。また、同等性または null テストにのみ参加する必要があります。この例では、データ内の ID を並べ替えるだけで、Quassnoi のソリューションを簡単に破ることができます。

本質的な問題は、グループ化による選言条件です。これにより、2 つのレコードが直接関連付けられるわけではありませんが、中間体を介して関連付けられる可能性が生じます。

たとえば、これらのレコードはすべてグループ化する必要があると述べました。

(1) ジョン 555-00-00 john@example.com

(2) ジョン 555-00-01 john@example.com

(3) ジョン 555-00-01 john-other@example.com

#1 と #2 は #2 と #3 と同様に関連性があることがわかりますが、明らかに #1 と #3 はグループとして直接関連性がありません。

これにより、再帰的または反復的なソリューションが唯一の可能なソリューションであることが確立されます。

そのため、簡単にループ状態になる可能性があるため、再帰は実行できません。これは、Quassnoi が ID 比較で回避しようとしていたことですが、そうすることで彼はアルゴリズムを破りました。再帰のレベルを制限することもできますが、すべてのリレーションを完了することはできず、ループをたどって自分自身に戻ってくる可能性があり、過剰なデータ サイズと法外な非効率性につながる可能性があります。

最良の解決策は繰り返しです。各 ID を一意のグループ ID としてタグ付けすることで結果セットを開始し、結果セットをスピンして更新し、ID を結合条件で一致する同じ一意のグループ ID に結合します。それ以上更新を行うことができなくなるまで、毎回更新されたセットに対してプロセスを繰り返します。

これについては、すぐにサンプル コードを作成します。

于 2010-10-19T14:50:57.323 に答える
0

この回答は、一時テーブルの使用について批判されることはわかっていますが、とにかく機能します。

-- create temp table to give the table a unique key
create table #tmp(
ID int identity,
can_Fname varchar(200) null, -- real type and len here
can_HPhone varchar(200) null, -- real type and len here
can_Email varchar(200) null, -- real type and len here
)

-- just copy the rows where a duplicate fname exits 
-- (better performance specially for a big table)
insert into #tmp 
select can_fname,can_hphone,can_email
from Can 
where can_fname exists in (select can_fname from Can 
group by can_fname having count(*)>1)

-- select the rows that have the same fname and 
-- at least the same phone or email
select can_Fname, can_Hphone, can_Email  
from #tmp a where exists
(select * from #tmp b where
a.ID<>b.ID and A.can_fname = b.can_fname
and (isnull(a.can_HPhone,'')=isnull(b.can_HPhone,'')
or  (isnull(a.can_email,'')=isnull(b.can_email,'') )
于 2009-07-02T17:37:25.963 に答える
0

このテーブルの主キーとして一意の ID 整数もあると仮定します。そうでない場合は、この目的や他の多くの目的のために、1 つ持っておくことをお勧めします。

自己結合によってそれらの重複を見つけます。

select
  c1.ID 
, c1.Can_FName
, c1.Can_HPhone
, c1.Can_Email
, c2.ID 
, c2.Can_FName
, c2.Can_HPhone
, c2.Can_Email
from
(
  select 
      min(ID), 
      Can_FName, 
      Can_HPhone, 
      Can_Email 
  from Can 
  group by 
      Can_FName, 
      Can_HPhone, 
      Can_Email
) c1
inner join Can c2 on c1.ID < c2.ID 
where
    c1.Can_FName = c2.Can_FName 
and (c1.Can_HPhone = c2.Can_HPhone OR c1.Can_Email = c2.Can_Email)
order by
  c1.ID

クエリは、N 個の重複する組み合わせごとに N-1 行を返します。一意の組み合わせごとにカウントするだけの場合は、「左側」でグループ化された行をカウントします。

select count(1) + 1,
, c1.Can_FName
, c1.Can_HPhone
, c1.Can_Email
from 
(
  select 
      min(ID), 
      Can_FName, 
      Can_HPhone, 
      Can_Email 
  from Can 
  group by 
      Can_FName, 
      Can_HPhone, 
      Can_Email
) c1
inner join Can c2 on c1.ID < c2.ID 
where
    c1.Can_FName = c2.Can_FName 
and (c1.Can_HPhone = c2.Can_HPhone OR c1.Can_Email = c2.Can_Email)
group by 
  c1.Can_FName
, c1.Can_HPhone
, c1.Can_Email

確かに、これはユニオンよりも複雑ですが、重複についての良い考え方を示していると思います。

于 2009-07-02T17:01:56.523 に答える
0

最初に派生テーブルから目的の変換を射影し、次に集計を行います。

SELECT COUNT(*) 
    , CAN_FName
    , Can_HPhoneOrEMail
    FROM (
        SELECT Can_FName 
            , ISNULL(Can_HPhone,'') +  ISNULL(Can_EMail,'')  AS Can_HPhoneOrEMail
        FROM Can) AS Can_Transformed
    GROUP BY Can_FName, Can_HPhoneOrEMail
    HAVING Count(*) > 1

派生テーブル プロジェクト リストで、必要に応じて「OR」演算を調整します。

于 2009-07-02T17:03:09.673 に答える