2011-07-22 5 views
19

私は2つのテーブルを持つデータベースを持っています。テーブルの1つにユーザーが含まれ、他のテーブルにはユーザーのアドレスが格納されます。SQL - 'DISTINCT'は一部の列のみに基づいていますか?

ユーザーごとに複数のアドレスがあっても、各ユーザーに対して1つのエントリしか返さない検索を作成したいと考えています。これは、ユーザーが複数のアドレスを持つ場合があります。どのアドレスに検索が戻ってくるかは問題ではありません。最初に検索で見つかったものであれば十分です。私はそれだけではなく、3

任意のアイデアよりも、2行を返すようなことを検索する必要がある

tst olix Chicago IL USA 
tst olix Los Angeles CA USA 
tst2 olix2 Houston TX USA 

:ここ

は、例えば、検索結果のですか?

SELECT DISTINCT 
    Users.Firstname, Users.Surname, Users.UserId, 
    Users.Recommendations, Addresses.City, Addresses.Region, 
    Addresses.Country 
FROM 
    Users INNER JOIN 
    Addresses ON FT_TBL.UserId = Addresses.UserId 
ORDER BY 
    Users.Recommendations 
+0

を何SQL ServerやAccessを使用していますか? –

+0

これがpostgresqlの場合は、DISTINCT ON構文を使用できます。 – sage88

答えて

8

AddressesIDフィールドがある場合:

(SQL-Serverの更新)

SELECT 
    Users.Firstname, 
    Users.Surname, 
    Users.UserId, 
    Users.Recommendations, 
    Addresses.City, 
    Addresses.Region, 
    Addresses.Country 
FROM 
    Users INNER JOIN 
    Addresses ON Users.UserId = Addresses.UserId 
WHERE Addresses.ID = 
    (SELECT TOP 1 A2.ID 
     FROM Addresses AS A2 
     WHERE Users.UserId = A2.UserId 
    ) 
ORDER BY 
    Users.Recommendations 

SQL-Serverのウィンドウを使用してランク付け機能:

SELECT 
    Users.Firstname, 
    Users.Surname, 
    Users.UserId, 
    Users.Recommendations, 
    Addresses.City, 
    Addresses.Region, 
    Addresses.Country 
FROM 
    Users INNER JOIN 
    (SELECT * 
      , ROW_NUMBER() OVER (PARTITION BY UserID) AS rn 
     FROM Addresses 
    ) AS Addresses ON Users.UserId = Addresses.UserId 
        AND Addresses.rn = 1 
ORDER BY 
    Users.Recommendations 
+0

それは私が使い終わった<比較よりも便利です。しかし、残念ながら、Microsoft SQLにはLIMITはありません。 – Oliver

+1

SQLサーバには「TOP」 –

+0

@Oliverがあります。また、この場合には便利なウィンドウ関数もあります。 –

7

あなたは、おそらくこのケースでGROUP BY代わりのDISTINCTを使用する必要があります。

あなたの質問を今投稿すると、さらにあなたを助けるでしょう。

また、の最初のアドレスを返すだけであれば、それはまったく別のクエリです。住所を返す必要がありますか?どのようなデータが必要ですか?この文脈で「最初」とは何を意味しますか?データはどのように注文されますか?

任意にあなたのDBに応じて、(未テスト)このような何かを行うことができます:

SELECT 
    userID 
    , FIRST(address) 
FROM 
    yourTable 
GROUP BY 
    userID 
+0

最終的には、それを位置検索にして、戻った結果が特定の場所に最も近い場所になるようにします。現時点では、私はサイトの設計作業中に何かを取り戻すだけです。 – Oliver

4
SELECT Name, MAX(Address), MAX(other field)... 
FROM MyTable 
GROUP BY Name 

はあなたにNameごとに1つの行を提供します。

+1

あなたの答えは、私のように、任意の順序に依存します。 OPは明確にする必要があります。 – Matthew

+3

@Matthew - 彼は質問で彼は彼がどの人が気にしないと言います。フィールドが相互に関連しているかどうかを気にすると思います(住所、市、州、郵便番号など) - 悪い状態/住所の組み合わせが間違っている可能性があります – JNK

+0

正確には、 IL |米国。 –

0

は集計してみてください:アドレステーブルを想定し

SELECT user, address FROM users 
JOIN addresses ON (users.user_id = addresses.user_id) 
GROUP BY user; 
4

は、id列があります。

select p.fname, p.lname, a.state, a.country 
from person p 
join address a on a.personid = p.personid 
where not exists 
    (select * 
    from address a2 
    where a2.personid = a.personid 
     and a2.addressid < a.addressid) 

私のクエリは、アドレスを持つすべての人々を返します。 exists()句を使用して、返されたアドレスがその人に割り当てられた最下位のアドレスIDを持つことを確認します。結果には1人あたり1つの住所しか含まれません。


EDIT:他の人によって示されていないtopを使用してこれを行うための別の方法:ネストされたクエリは、最初のアドレスに短絡それぞれが見つかりますよう

select p.fname, p.lname, a.state, a.country 
from person p 
join address a on a.addressid = 
    (select top 1 a2.addressid 
    from address a2 
    where a2.personid = p.personid) 

これは非常に効率的でなければなりません人。

+0

ありがとう、私はこれをスロットに入れるのが一番簡単だと分かりました。ユーザー/アドレスIDが数字ではなく英数字であってもうまくいくようです。この方法が遅いという問題はありますか?私はそれが生成されている各結果の2番目の検索をしているに違いないと思います。 – Oliver

+0

私はあなたが何であってもあなたのクエリでアドレステーブルを2回参照する必要があると思います。 ypercubeが持っている 'top' selectは' exists() 'より速いかもしれません。しかし、確かに言うのは難しいですし、私はこの技術を何度も遅く気付かずに使っています。 – dana

関連する問題