2011-07-22 74 views
19

我有兩個表的數據庫。其中一個表包含用戶,另一個包含這些用戶的地址。每個用戶可以有幾個IP地址(但每個地址綁定到只有一個用戶。)SQL - 僅基於某些列的「DISTINCT」?

我想創建一個搜索只返回爲每個用戶一個條目,即使該用戶有多個地址。無論搜索找到哪個地址,搜索的哪個地址都會回退並不重要。

下面是一個例子搜索結果:

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

我需要的搜索是這樣的,它只返回兩行,而不是3

任何想法?

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服務器)

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

這看起來比我最後使用的<比較更方便。但是,唉,微軟的SQL沒有限制。 – Oliver

+1

SQL-Server具有'TOP' –

+0

@Oliver:還有在這種情況下應該很方便的窗口函數。 –

7

你可能需要在這種情況下使用GROUP BY,而不是DISTINCT

發表您的查詢,現在我會幫助你更多。

或者,如果您只是想返回第一個地址,那麼這是完全不同的查詢。是否需要返回地址?你需要什麼數據?在這種情況下,「第一」意味着什麼?數據如何訂購?

隨意,你可以做這樣的事情(未經測試),這取決於您的數據庫:

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--他在問題中說他不關心他得到哪一個。我認爲他可能在乎這些字段是否相互關聯(即Address1,City,State,Zip) - 你可能會得到錯誤的狀態/地址組合,這會很糟糕 – JNK

+0

就是這樣:'Los Angeles | IL | USA'。 –

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()子句用於確定返回的地址具有分配給該人的最低addressid。結果將只包含每個人1個地址。


編輯:另一種方式來做到這一點使用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是字母數字,而不僅僅是數字。這種方法速度慢嗎?我猜想它必須對每個生成的結果進行第二次搜索。 – Oliver

+0

我認爲你不得不在你的查詢中兩次引用地址表。 ypercube所具有的'top'可能實際上比我的'exists()'快。然而,很難確切地說,我已經多次使用這種技術,卻沒有注意到太多的減速。 – dana