2012-06-11 29 views
16

The question you're asking appears subjective and is likely to be closed.SQL chọn những người mà bạn có thể biết

Tôi không ngạc nhiên khi tôi đã thấy ở trên cảnh báo khủng khiếp trong khi tôi đang làm trong lĩnh vực tiêu đề.

Tôi đọc hầu hết mọi chủ đề nói về friends of friends hoặc mutual friends nhưng tôi không chắc mình đã tìm được giải pháp phù hợp mà tôi muốn làm.

Tôi xin lỗi vì tôi không giỏi tiếng Anh và SQL.

Tôi làm cách nào để tìm câu trả lời đúng khi không giỏi ở cả hai ngôn ngữ?

Tôi quyết định tôi phải hỏi. Tôi sẽ không để bản thân mình xuống cho down-vote s hoặc bất kỳ duplication warning s.

Khi tôi muốn câu trả lời, tôi sẽ viết ra càng chân thành càng tốt cho bất kỳ vấn đề tương tự nào khác có thể được trợ giúp.

Tôi có bảng quan hệ bạn bè.

FRIEND (TABLE) 
----------------------------------- 
PLAYER_ID(PK,FK) FRIEND_ID(PK,FK) 
----------------------------------- 
1     2     // 1 knows 2 
2     1     // 2 knows 1 
1     3     // 1 knows 3 
2     3     // 2 knows 3 
2     4     // 2 knows 4 
2     5     // 2 knows 5 // updated 
3     5     // 3 knows 5 // updated 
1     100 
1     200 
1     300 
100    400 
200    400 
300    400 

Cả hai composite primary keys cũng là khóa ngoài từ PLAYER bảng.

Tôi đã hỏi và được trả lời từ những người tuyệt vời như vậy vì "mọi người biết nhau".

SQL view for acquaintance from table.

Và tôi có chế độ xem như thế này.

ACQUAINTANCE (VIEW) 
----------------------------------- 
PLAYER_ID(PK,FK) FRIEND_ID(PK,FK) 
----------------------------------- 
1     2     // 1 knows 2 
2     1     // 2 knows 1 

Như bạn có thể thấy, logic kinh doanh của các mối quan hệ này có hai mục đích.

  1. Một người chơi có thể nói họ biết người khác.
  2. Khi cả hai người nói rằng họ biết nhau, họ có thể nói là người quen.

Và, bây giờ, tôi muốn biết là có cách nào tốt cho

  1. Chọn PLAYER_IDs khác
  2. Với PLAYER nhất định (PLAYER_ID) (nói 1)
  3. nào từng là một trong những `bạn bè của những người bạn trực tiếp của PLAYER '
  4. Mỗi người chơi không phải là NGƯỜI CHƠI (trừ 1 -> 2 -> 1)
  5. Mỗi người chơi không phải là người bạn trực tiếp của NGƯỜI CHƠI (không bao gồm 3 người 1 -> 2 -> 3 x 1 -> 3)
  6. Đặt hàng theo số lượng bạn bè chung nếu có thể.

Tôi nghĩ câu trả lời của Justin Niessner ở "people you may know" sql query là con đường gần nhất mà tôi phải tuân theo.

Xin cảm ơn trước.

Tôi sẽ đóng chuỗi nếu chủ đề này thực sự bị trùng lặp và không cần thiết.

CẬP NHẬT --------------------------------------------- -----------------

bình luận Raphaël Althaus của whose name is same with my future daughter (là nó tên cậu bé không?),

3 là một ứng cử viên cho friends of friends of 1

1 knows 2 
2 knows 3 

nhưng bị loại trừ vì

1 already knows 3 

Về cơ bản tôi muốn phục vụ cho việc given player các

people he or she may know 
which is not himself or herself // this is nothing but obvious 
which each is not already known to himself 

Với bảng trên

by 1 -> 2 -> 4 and 1 -> 3 -> 5 

4 and 5 can be suggested for 1 as 'people you may know' 

order by number of mutual friends will be perfect 
but I don't think I can understand even if someone show me how. sorry. 

Cảm ơn bạn.

CẬP NHẬT --------------------------------------------- ------------------------

Tôi nghĩ tôi phải tự mình từng bước một từ những gì tôi đã học được FROM HERE WITH VARIOUS PEOPLE ngay cả khi nó không phải là câu trả lời đúng. Vui lòng cho tôi biết nếu tôi đang làm gì sai.

Trước hết, hãy để tôi tự tham gia vào bảng FRIEND.

SELECT * 
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID 

in

+-----------+-----------+-----------+-----------+ 
| PLAYER_ID | FRIEND_ID | PLAYER_ID | FRIEND_ID | 
+-----------+-----------+-----------+-----------+ 
|   1 |   2 |   2 |   1 | 
|   1 |   2 |   2 |   3 | 
|   1 |   2 |   2 |   4 | 
|   1 |   2 |   2 |   5 | 
|   1 |   3 |   3 |   5 | 
|   2 |   1 |   1 |   2 | 
|   2 |   1 |   1 |   3 | 
|   2 |   3 |   3 |   5 | 
+-----------+-----------+-----------+-----------+ 

F2.FRIEND_ID chỉ

SELECT F2.FRIEND_ID 
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID 

in

+-----------+ 
| FRIEND_ID | 
+-----------+ 
|   1 | 
|   3 | 
|   4 | 
|   5 | 
|   5 | 
|   2 | 
|   3 | 
|   5 | 
+-----------+ 

cho 1 chỉ

SELECT F2.FRIEND_ID 
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID 
WHERE F1.PLAYER_ID = 1; 

in

+-----------+ 
| FRIEND_ID | 
+-----------+ 
|   1 | 
|   3 | 
|   4 | 
|   5 | 
|   5 | 
+-----------+ 

không 1

SELECT F2.FRIEND_ID 
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID 
WHERE F1.PLAYER_ID = 1 
AND F2.FRIEND_ID != 1; 

in

+-----------+ 
| FRIEND_ID | 
+-----------+ 
|   3 | 
|   4 | 
|   5 | 
|   5 | 
+-----------+ 

không 1 của knowns trực tiếp

SELECT F2.FRIEND_ID 
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID 
WHERE F1.PLAYER_ID = 1 
AND F2.FRIEND_ID != 1 
AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = 1); 

in

+-----------+ 
| FRIEND_ID | 
+-----------+ 
|   4 | 
|   5 | 
|   5 | 
+-----------+ 

Tôi nghĩ mình sẽ đến đó.

CẬP NHẬT --------------------------------------------- --------------------

đường dẫn sau thêm

1 -> 100 -> 400 
1 -> 200 -> 400 
1 -> 300 -> 400 

Và các bản in truy vấn cuối cùng (một lần nữa)

+-----------+ 
| FRIEND_ID | 
+-----------+ 
|   4 | 
|   5 | 
|   5 | 
|  400 | 
|  400 | 
|  400 | 
+-----------+ 

tại cuối cùng, tôi đã nhận được các ứng cử viên: 4, 5, 400

Đưa distinct chắc chắn làm việc cho mục tiêu chính

SELECT DISTINCT F2.FRIEND_ID 
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID 
WHERE F1.PLAYER_ID = 1 
AND F2.FRIEND_ID != 1 
AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = 1); 

in

+-----------+ 
| FRIEND_ID | 
+-----------+ 
|   4 | 
|   5 | 
|  400 | 
+-----------+ 

Và, bây giờ, ra lệnh bằng cách đếm lẫn nhau cần thiết.

Ở đây có số lượng bạn bè chung cho mỗi ứng cử viên.

+-----------+ 
| FRIEND_ID | 
+-----------+ 
|   4 | 1 (1 -> 2 -> 4) 
|   5 | 2 (1 -> 2 -> 5, 1 -> 3 -> 5) 
|  400 | 3 (1 -> 100 -> 400, 1 -> 200 -> 400, 1 -> 300 -> 400) 
+-----------+ 

Tôi có thể tính toán và sắp xếp theo số lượng bạn bè chung đó như thế nào?

SELECT F2.FRIEND_ID, COUNT(*) 
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID 
WHERE F1.PLAYER_ID = 1 
AND F2.FRIEND_ID != 1 
AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = 1) 
GROUP BY F2.FRIEND_ID; 

in

+-----------+----------+ 
| FRIEND_ID | COUNT(*) | 
+-----------+----------+ 
|   4 |  1 | 
|   5 |  2 | 
|  400 |  3 | 
+-----------+----------+ 

tôi đã nhận nó!

SELECT F2.FRIEND_ID, COUNT(*) AS MFC 
FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID 
WHERE F1.PLAYER_ID = 1 
AND F2.FRIEND_ID != 1 
AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = 1) 
GROUP BY F2.FRIEND_ID 
ORDER BY MFC DESC; 

in

+-----------+-----+ 
| FRIEND_ID | MFC | 
+-----------+-----+ 
|  400 | 3 | 
|   5 | 2 | 
|   4 | 1 | 
+-----------+-----+ 

Ai có thể xin xác nhận điều này? Truy vấn đó có tối ưu không? Bất kỳ vấn đề hiệu suất có thể xảy ra khi làm cho nó như là một cái nhìn?

Cảm ơn bạn.

CẬP NHẬT --------------------------------------------- -----------------------------------------------

Tôi đã tạo chế độ xem là

CREATE VIEW FOLLOWABLE AS 
    SELECT F1.PlAYER_ID, F2.FRIEND_ID AS FOLLOWABLE_ID, COUNT(*) AS MFC 
    FROM FRIEND F1 INNER JOIN FRIEND F2 ON F1.FRIEND_ID = F2.PLAYER_ID 
    WHERE F2.FRIEND_ID != F1.PLAYER_ID 
    AND F2.FRIEND_ID NOT IN (SELECT FRIEND_ID FROM FRIEND WHERE PLAYER_ID = F1.PLAYER_ID) 
    GROUP BY F2.FRIEND_ID 
    ORDER BY MFC DESC; 

và thử nghiệm.

mysql> select * from FOLLOWABLE; 
+-----------+---------------+-----+ 
| PlAYER_ID | FOLLOWABLE_ID | MFC | 
+-----------+---------------+-----+ 
|   1 |   400 | 3 | 
|   1 |    5 | 2 | 
|   2 |   100 | 1 | 
|   2 |   200 | 1 | 
|   2 |   300 | 1 | 
|   1 |    4 | 1 | 
+-----------+---------------+-----+ 
6 rows in set (0.01 sec) 

mysql> select * from FOLLOWABLE WHERE PLAYER_ID = 1; 
+-----------+---------------+-----+ 
| PlAYER_ID | FOLLOWABLE_ID | MFC | 
+-----------+---------------+-----+ 
|   1 |   400 | 3 | 
|   1 |    5 | 2 | 
|   1 |    4 | 1 | 
+-----------+---------------+-----+ 
3 rows in set (0.00 sec) 
+1

điểm 1 => 3 không phải là rõ ràng tại của tôi đôi mắt (nghèo). Bạn có thể cung cấp một tập hợp dữ liệu và kết quả chính xác mà bạn muốn truy xuất, có thể (hoặc chỉ là kết quả bạn muốn nếu tập hợp dữ liệu của bạn là đủ). –

+1

Bạn có mong đợi kết quả SQL trả về 4 không? –

+2

Đối với những gì nó có giá trị, bạn đang áp dụng một chi nhánh của toán học được gọi là lý thuyết đồ thị. Nếu bạn sẽ làm bất cứ điều gì nhiều hơn một số lượng nhỏ của công việc về vấn đề này, bạn sẽ được khôn ngoan để đọc một cuốn sách về điều đó. Nó có nhiều tinh tế. Để được tư vấn về cách tìm hiểu tài liệu đó, hãy thử programmers.stackexchange.com –

Trả lời

7

sử dụng này EDIT

SELECT `friend_id` AS `possible_friend_id` 
FROM `friends` 
WHERE `player_id` IN (  --selecting those who are known 
    SELECT `friend_id`  --by freinds of #1 
    FROM `friends` 
    WHERE `player_id` = 1) 
AND `friend_id` NOT IN (  --but not those who are known by #1 
    SELECT `friend_id` 
    FROM `friends` 
    WHERE `player_id` = 1) 
AND NOT `friend_id` = 1  --and are not #1 himself 
           --if one is known by multiple people 
           --he'll be multiple time in the list 
GROUP BY `possible_friend_id` --so we group 
ORDER BY COUNT(*) DESC  --and order by amount of repeatings 
+0

Cảm ơn câu trả lời của bạn, thưa ngài. Tôi hiểu điều kiện thứ 2 và thứ 3. Nhưng tôi khó có thể hiểu được điều kiện thứ nhất. Đây thực sự là một truy vấn cho việc tìm kiếm 'bạn bè của bạn bè'? –

+0

, tôi chọn tất cả bạn bè của tất cả người chơi là bạn của 1 – Valerij

+0

Tôi ngạc nhiên khi truy vấn của bạn hiển thị chính xác kết quả tương tự với kết quả của tôi. Cảm ơn bạn. Bạn có thể vui lòng dành một vài phút để đặt hàng bởi số lượng bạn bè lẫn nhau? –

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