2011-07-11 2 views
0

私はテーブルにログインと電話の列があり、私はテーブルのジオフォンに列とマスクが含まれています。INNER JOINの結果に重複したログインが含まれています

電話機はvarchar( "+380981234567")として保存されます。マスクはvarchar( "+38098")として格納されます。マスクは重複しています(例えば、+380と+38098)。

ユーザとジオフォンテーブルを結合し、最も長い時間マッチしたマスクでログインごとにリージョンを割り当てるビューが必要です。

私は、以下のSQL文を書きましたが、結果は重複したログインが含まれており、私はこの問題を回避する方法がわからない:

SELECT TOP (5000) 
    Users.Login, Users.Phone, GeoPhone.Region, LEN(GeoPhone.Mask) AS MaskLen 
FROM Users 
INNER JOIN GeoPhone ON LEFT(Users.Phone, LEN(GeoPhone.Mask)) = GeoPhone.Mask 
ORDER BY Users.Login, MaskLen DESC 

それを改善するために助けてください。

+0

ありますか? –

答えて

2

これを実行する方法の1つは、SQL 2005以降でのクロス・アプライを使用することです。

SELECT 
    TOP (5000) Users.Login, 
    Users.Phone, 
    GeoPhone.Region, 
    LEN(GeoPhone.Mask) AS MaskLen 
FROM Users 
    CROSS APPLY 
    (
     SELECT TOP 1 Region,Mask 
     FROM geophone 
     WHERE LEFT (users.phone, Len(geophone.mask)) = geophone.mask 
     ORDER BY 
      Len(geophone.mask) DESC 
     ) geophone 

ジオフォンから1つのレコードしか返さないことに注意してください。マスクの長さのためにネクタイgeophone.maskに2つのレコードがある場合は、それが

を返しますどのレコードを決定することはできませんここでMAXを使用します(溶液)だとそのrealtivelyポータブル

SELECT TOP (5000) users.LOGIN, 
        users.phone, 
        geophone.region, 
        Len(geophone.mask) AS masklen 
FROM users 
     INNER JOIN geophone 
     ON LEFT(users.phone, Len(geophone.mask)) = geophone.mask 
     INNER JOIN (SELECT MAX(Len(geophone.mask)) maxlength, 
          users.phone 
        FROM users 
          INNER JOIN geophone 
          ON LEFT(users.phone, Len(geophone.mask)) = 
           geophone.mask 
        GROUP BY users.phone) t 
     ON t.phone = users.phone 
      AND t.maxlength = Len(geophone.mask) 

しかし、ジオフォンの2つの列が長さが最も長い場合、両方の結果が返されます。これがあなたのために良いか悪いのか分かりません。

また、SQL 2005でROW_NUMBERを使用したりすることができ、後にSQLサーバーのバージョンまた、あなたは「最長一致マスク」のネクタイがあります受振器に2つのレコードを持っている場合やりたい何

+0

"CROSS APPLY SQL構文または文はサポートされていません。私は開発時に私のdevサーバとMS SQL 2005でMS SQL 2005 Expressを使用しています。 – Denis

+0

@Denisより移植性の高いバージョンを追加しましたが、Tiesの問題を書き留めてください。 –

+0

@Denis互換モードで動作している可能性があります。 'sp_dbcmptlevel 'YourDbname''を実行することでこれを確認することができます。もし80であれば、SQL 2005のいくつかのことは動作しません。 –

0

DISTINCTキーワードを使用すると、重複した結果を削除できます。しかし、あなたのロジックは実際には、このキーワードを使用してハックあなたの結果ではなく、実際には音です。つまり、結合ロジックに何らかのエラーがあるため、結果が重複しているだけです。あなたのケースでは、名前のために複数の結果を持つことが有効であれば、それは有効です。

SELECT DISTINCT TOP (5000) 
    Users.Login, 
    Users.Phone, 
    GeoPhone.Region, 
    LEN(GeoPhone.Mask) AS MaskLen 
FROM Users 
    INNER JOIN GeoPhone ON LEFT(Users.Phone, LEN(GeoPhone.Mask)) = GeoPhone.Mask 
ORDER BY Users.Login, MaskLen DESC 
+0

私はこれがOPの "each long by matched mask"に合っているとは思わない要件 –

+0

私はこれを前に試しましたが、うまくいきませんでした。 – Denis

0
select top (5000) 
    users.login, 
    users.phone, 
    geophone.region, 
    max(len(geophone.mask)) as masklen 
from users 
inner join geophone on left(users.phone, len(geophone.mask)) = geophone.mask 
group by users.login, users.phone, geophone.region 
order by users.login, masklen desc 
+0

JOINが同じログイン用に異なるLogin-Phone-Regionペアを返し、GROUP BYがフィルタリングしないため、最初の質問を投稿する前にこれを試しました。これはアウト。 – Denis

関連する問題