2011-07-22 66 views
19

Tôi có một cơ sở dữ liệu với hai bảng. Một trong các bảng chứa người dùng, người kia chứa địa chỉ cho những người dùng đó. Mỗi người dùng có thể có một số địa chỉ (mặc dù mỗi địa chỉ chỉ được gắn với một người dùng.)SQL - 'DISTINCT' chỉ dựa trên một số cột?

Tôi muốn tạo tìm kiếm chỉ trả về một mục cho mỗi người dùng, ngay cả khi người dùng đó có một số địa chỉ. Nó không quan trọng đến địa chỉ tìm kiếm kéo trở lại - bất cứ điều gì tìm kiếm tìm thấy đầu tiên là đủ.

Dưới đây là một ví dụ kết quả tìm kiếm:

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

Tôi cần tìm kiếm để được như vậy mà nó chỉ trả về 2 hàng, chứ không phải 3.

Bất kỳ ý tưởng?

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

gì bạn có sử dụng, SQL-Server hoặc Access? –

+0

Nếu đây là postgresql bạn chỉ có thể sử dụng cú pháp DISTINCT ON. – sage88

Trả lời

8

Nếu AddressesID lĩnh vực:

(cập nhật cho 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 

Sử dụng cửa sổ SQL Server và xếp hạng các chức năng:

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

Có vẻ tiện dụng hơn so với Oliver

+1

SQL-Server có 'TOP' –

+0

@Oliver: Và cũng có các chức năng cửa sổ cần tiện dụng trong trường hợp này. –

7

Bạn có thể cần phải sử dụng GROUP BY thay vì DISTINCT trong trường hợp này.

Đăng truy vấn của bạn ngay bây giờ và tôi sẽ giúp bạn nhiều hơn.

Hoặc, nếu bạn chỉ muốn trả lại địa chỉ đầu tiên, đó là một truy vấn khác hoàn toàn. Có cần trả lại địa chỉ không? Bạn cần dữ liệu nào? "Thứ nhất" có ý nghĩa gì trong ngữ cảnh này? Dữ liệu được sắp xếp như thế nào?

Tự ý bạn có thể làm một cái gì đó như thế này (chưa được kiểm tra), tùy thuộc vào DB của bạn:

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

Cuối cùng tôi muốn nó là một tìm kiếm vị trí, và kết quả kéo trở lại là nơi gần nhất với một vị trí nhất định. Tại thời điểm này tôi chỉ muốn nó kéo trở lại một cái gì đó trong khi tôi làm việc trên thiết kế của trang web. – Oliver

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

sẽ cung cấp cho bạn một hàng cho mỗi Name.

+1

+1 câu trả lời của bạn, như tôi phụ thuộc vào một số thứ tự tùy ý. OP nên làm rõ. – Matthew

+3

@Matthew - anh ấy nói trong câu hỏi anh ấy không quan tâm anh ta nhận được cái nào. Tôi nghĩ anh ấy có thể quan tâm nếu các trường có liên quan đến nhau (ví dụ: 'Address1, City, State, Zip') - bạn có thể nhận nhầm kết hợp tiểu bang/địa chỉ sẽ là xấu – JNK

+0

Chính xác, như:' Los Angeles | IL | USA'. –

0

Hãy thử một tổng hợp:

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

Giả sử bảng địa chỉ có một cột 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) 

truy vấn của tôi trả về tất cả những người có địa chỉ. Mệnh đề exists() được sử dụng để xác định rằng địa chỉ trả về có địa chỉ thấp nhất được gán cho người đó. Kết quả sẽ chỉ chứa 1 địa chỉ cho mỗi người.


EDIT: Một cách khác để làm điều này bằng top chưa được chứng minh bởi những người khác:

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) 

này nên rất hiệu quả như truy vấn lồng nhau sẽ ngắn mạch trên địa chỉ đầu tiên tìm thấy cho mỗi người.

+0

Cảm ơn, tôi đã tìm thấy cái này dễ nhất để sắp xếp. Có vẻ như nó hoạt động mặc dù id người dùng/địa chỉ của tôi là chữ và số thay vì chỉ là số. Có bất kỳ vấn đề với phương pháp này đang chậm? Tôi cho rằng nó phải thực hiện tìm kiếm thứ hai cho mỗi kết quả được tạo ra. – Oliver

+0

Tôi nghĩ rằng bạn phải tham khảo bảng địa chỉ hai lần trong truy vấn của bạn bất kể điều gì. 'Top' chọn ypercube có thể thực sự nhanh hơn' exist() 'của tôi. Tuy nhiên, thật khó để nói chắc chắn và tôi đã sử dụng kỹ thuật này nhiều lần mà không nhận thấy quá nhiều sự chậm lại. – dana

Các vấn đề liên quan