0

テーブルには NAME 列と DISTANCE 列があります。同じ名前から N ユニット以内にあるすべての名前をリストする方法を見つけたいと思います。すなわち与えられた:

NAME    DISTANCE
a   2
a   4
a   3
a   7
a   1
b   3
b   1
b   2
b   5

(N = 2 としましょう)

a 2 
a 4 
a 3
a 1
...
...

2 a 2 の代わりに (二重にカウントされるため)

このメソッドを適用して、互いにクラスターに表示される請求日 (数値として格納されている) を持つ customerID を解決しようとしています。customerID と、同じ顧客による別の請求から 10 日以内の請求日をラベル付けできるようにしたいと考えています。つまり、|a.claimdate - b.claimdate| <= 10.このメソッドを使用すると

WHERE a.CUSTID = b.CUSTID
AND a.CLDATE BETWEEN (b.CLDATE - 10 AND b.CLDATE + 10)
AND a.CLAIMID <> b.CLAIMID

ダブルカウントします。CLAIMID はユニークです。

4

2 に答える 2

2

テキストは必要なく、値だけが必要なため、次を使用してそれを実現できますDISTINCT

select distinct t.name, t.distance
from yourtable t
  join yourtable t2 on t.name = t2.name 
    and (t.distance = t2.distance+1 or t.distance = t2.distance-1)
order by t.name

SQL フィドルのデモ

編集を考慮して、特定の距離の間の結果を探している場合は、>= と <= (または BETWEEN) を使用できます。

select distinct t.name, t.distance
from yourtable t
  join yourtable t2 on t.name = t2.name 
    and t.distance >= t2.distance-1 
    and t.distance <= t2.distance+1
    and t.distance <> t2.distance
order by t.name

t.distance <> t2.distanceデータセット全体を返さないように、最後の基準を追加する必要があります。技術的には、すべての距離はそれ自体の間にあります。結合に追加する主キーがある場合はこれが適していますが、そうでない場合はROW_NUMBER()、同じ結果を得るためにも使用できます。

with cte as (
  select name, distance, row_number() over (partition by name order by (select null)) rn
  from yourtable
  )
select distinct t.name, t.distance
from cte t
  join cte t2 on t.name = t2.name 
    and t.distance >= t2.distance-1
    and t.distance <= t2.distance+1
    and t.rn <> t2.rn
order by t.name

更新された SQL フィドル

于 2013-05-09T19:39:49.060 に答える
1

@sgeddesソリューションが気に入っていますが、次のように個別orの結合条件を取り除くこともできます。

select * from table a
where exists (
    select 1 from table b
    where b.name = a.name
        and b.distance between a.distance - 1 and a.distance + 1
)

これにより、 @HABOnで提案されているように、距離の差が正確にある行だけでなく、距離が等しい行が含まれ、範囲全体が考慮されます。

于 2013-05-09T19:46:26.747 に答える