2012-03-07 44 views
5

Tôi có các bảng users, locations và bảng tham gia. Bảng kết nối cũng có một giá trị xếp hạng cho mỗi cá nhân tại vị trí đó, bởi vì những cá nhân đó có thứ hạng cao hơn tại các vị trí nhất định hơn tại các vị trí khác.Loại Tham gia nào để xem các giá trị không tồn tại trong bảng Tham gia?

users 
========= 
id | name 
========= 
1 | john 
2 | bob 
3 | alex 

locations 
=============== 
id | name 
=============== 
1 | san diego 
2 | dallas 
3 | new york 
4 | denver 

join_users_locations 
============================== 
user_id | location_id | rank 
============================== 
     2 |   1 | 4 
     2 |   2 | 3 
     2 |   4 | 2 
     3 |   1 | 2 
     3 |   2 | 4 

Bạn có thể thấy rằng trong bảng tham gia, người dùng chỉ được liệt kê nếu họ có xếp hạng tại vị trí đó. Họ không phải là ngay cả trong bảng nếu thứ hạng của họ là số không/null.

Tôi muốn để có được kết quả truy vấn như thế này:

name | location | rank 
======================= 
bob | san diego | 4 
bob | dallas | 3 
bob | new york | 0 
bob | denver | 2 

Như bạn thấy, tôi muốn tất cả các địa điểm để có trong danh sách, thậm chí những người mà người dùng không tham gia với (chỉ cần cung cấp cho các trường đó có giá trị xếp hạng là 0).

Thật dễ dàng để có được danh sách các địa điểm và đứng thứ cho các địa điểm anh/cô ấy được nối với:

SELECT 
    u.name, 
FROM users u 
LEFT JOIN join_users_locations jul ON jul.user_id = u.id 
LEFT JOIN locations l ON l.id = jul.location_id 
WHERE u.id = 2 

Nhưng đó chỉ liệt kê những gì các địa điểm người dùng sẽ được tham gia với. Tôi cũng muốn xem các vị trí không tham gia.

Tôi biết điều này là có thể, nhưng tôi không chắc chắn giải pháp là gì. Tôi đã thử một số loại JOIN khác nhau với các kết quả khác nhau.

SQL FIDDLE HERE

+0

Cậu cố gắng rời bên ngoài tham gia? – Ciprian

Trả lời

3

Bạn có thể làm điều này với một CROSS JOINusers-locations.

SELECT 
    u.name, 
    l.name AS location, 
    IFNULL(jul.rank, 0) AS rank 
FROM 
    users u CROSS JOIN 
    locations l LEFT JOIN 
    join_users_locations jul 
     ON jul.user_id = u.ID 
     AND jul.location_id = l.id 
WHERE u.id = 2 
+1

Ah thú vị ... không bao giờ sử dụng CROSS JOIN trước đây. Có nó hoạt động hoàn hảo ở đây: http://sqlfiddle.com/#!2/4a46a/8 Cảm ơn –

0

Left ngoài tham gia. Các phép nối ngoài bao gồm mọi thứ "ở bên trái" của phép nối, ngay cả khi không có tuple tương ứng ở bên trái. Bạn có thể sẽ nhận được null thay vì 0, mặc dù. Ổn chứ? (bạn có thể thiết lập hiển thị giá trị null là 0, nếu không muốn nói)

+1

Như thế này? http://sqlfiddle.com/#!2/4a46a/4 Không thể làm điều đó. Tuy nhiên, –

+1

tất cả các giá trị bạn đã chèn đều có xếp hạng. Nếu tôi thay đổi một trong các chèn để có một thứ hạng của null và chạy lại nó tôi nhận được chính xác những gì bạn muốn. Ngoại trừ một khoảng trống thay vì 0. http://sqlfiddle.com/#!2/9f52c/2 – Colleen

+0

Tôi không theo dõi. Bạn có thể sao chép/dán url SQL Fiddle không? –

0
SELECT u.name,l.name as location,jul.rank 
FROM users u,locations l,join_users_locations jul 
WHERE u.id = jul.user_id AND 
     jul.location_id = l.id AND 
     u.id = 2 
UNION 
SELECT 'bob' AS NAME,A.NAME AS location,A.RANK_NULL AS RANK 
FROM 
(SELECT *,IFNULL(RANK,0) AS RANK_NULL 
FROM (SELECT * FROM JOIN_USERS_LOCATIONS JUL WHERE JUL.USER_ID=2)JUL 
RIGHT JOIN LOCATIONS L 
    ON JUL.LOCATION_ID = L.ID 
WHERE RANK IS NULL)A 

HOẶC

SELECT IFNULL(JUL.NAME,'bob'),L.NAME,IFNULL(RANK,0) AS RANK 
FROM (SELECT U.NAME,JUL.USER_ID,JUL.LOCATION_ID,JUL.RANK 
     FROM USERS U,JOIN_USERS_LOCATIONS JUL 
     WHERE U.ID=JUL.USER_ID AND JUL.USER_ID=2 
    ) JUL 
     RIGHT JOIN 
     LOCATIONS L 
    ON JUL.LOCATION_ID = L.ID 
+0

Sự tham gia ngầm định trong mệnh đề where sẽ có tác dụng tương tự như thực hiện các phép nối bên trong ... jul.rank sẽ không bao giờ rỗng, và điều này không thể trả về bất kỳ vị trí nào mà người dùng không có bản ghi trong 'join_user_locations' ... –

+0

Làm cho nó rất phức tạp đối với các bạn ... :) – Teja

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