2012-02-29 25 views
6

Tôi đang xây dựng hệ thống trả lời bình luận lồng nhau trong ứng dụng của mình.Cách kết hợp các truy vấn MySQL này và sau đó truy cập dữ liệu chính xác

Mọi thứ hiện đang hoạt động như dự định tuy nhiên tôi thấy mình phải sử dụng một số truy vấn MySQL để truy xuất dữ liệu cần thiết. Và thậm chí tệ hơn truy vấn cho 'trả lời' nằm trong vòng lặp foreach. Có nghĩa là mặc dù nó thực hiện đáng ngưỡng mộ cho bây giờ, nó là xa tối ưu và sẽ gây ra vấn đề như tập dữ liệu phát triển.

Vì vậy, tôi muốn giải quyết vấn đề này trước khi tôi phát triển sâu hơn.

Vì các bảng cho ứng dụng này giống như blog wordpress cho trang web tôi đang sử dụng viết tắt wordpress cho các truy vấn.

Cách hiện tại trang web được tạo ra như sau:

Một bảng bình luận được truy vấn và tất cả các kết quả liên quan đến một projectid được lấy ra: -

$commentquery = "select projects_comments.*, users.user_url, users.display_name 
       from ".$wpdb->prefix."projects_comments projects_comments 
       left join ".$wpdb->prefix."users users on users.ID=projects_comments.userid 
       where projectid = '$projectid' 
       order by projects_comments.commentid desc 
       "; 

$comments = $wpdb->get_results($commentquery); 

sau đó tôi thực hiện một vòng lặp foreach như sau : -

if($comments) { 
      foreach ($comments as $c) 
       { 


       $replyquery = "select project_replies.*, users.user_url, users.display_name 

       from ".$wpdb->prefix."project_replies project_replies 
       left join ".$wpdb->prefix."users users on users.ID=project_replies.uid 
       where project_replies.cid = '$c->commentid' 
       order by project_replies.id desc   
       limit 2   
       ";  

       $replies = $wpdb->get_results($replyquery); 

       asort($replies); 

       $countquery = "select count(*) 

        from ".$wpdb->prefix."project_replies project_replies 
        where project_replies.cid='".$c->commentid."' 
        "; 

       $replycount = $wpdb->get_var($countquery); 

    //generate html here 
    } 
} 

Bên trong vòng lặp này là hai truy vấn nữa. Đầu tiên nhận được câu trả lời cho mỗi nhận xét nhưng giới hạn kết quả thành 2 (Tôi muốn thực hiện việc này để có nút "xem tất cả câu trả lời" sau đó truy vấn DB cho phần còn lại nếu người dùng yêu cầu), số truy vấn thứ hai tổng số câu trả lời.

Các html sau đó cũng tạo ra cho mỗi câu trả lời trong vòng lặp sử dụng một foreach lồng thứ hai trong vòng lặp ở trên (nơi nó nói tạo mã html ở đây) như sau: -

if ($replies){ 

    foreach ($replies as $r){ 

    // generate each reply 
    } 
} 

Tất cả dữ liệu được kéo từ các mảng này theo cách sau:

$c->userid, $c->body etc... For the comments 
$r->userid, $r->body etc... For the replies. 

Tôi muốn giữ định dạng này nếu có thể. Vì vậy, như đã nêu ở phần đầu của câu hỏi, tất cả điều này hoạt động hoàn hảo tuy nhiên tôi biết rằng bằng cách lồng trả lời và đếm truy vấn, tôi đang thực hiện nhiều truy vấn hơn mức cần thiết. 100 nhận xét sẽ tạo ra 100 truy vấn trả lời và 100 truy vấn trả lời tính, v.v.

Nhờ một số người hữu ích trên trang web này, tôi đã xem xét sử dụng tham gia để nhận tất cả dữ liệu gốc một lần cho nhận xét và trả lời. Giống như vậy ...

$commentquery2 = "SELECT c.commentid, c.userid, c.body as cbody, c.projectid, c.posttime, cu.user_url AS cu_url, cu.display_name AS cu_name, 
        r.*, ru.user_url AS ru_url, ru.display_name AS ru_name 
       FROM ".$wpdb->prefix."projects_comments AS c 
       LEFT JOIN ".$wpdb->prefix."users  AS cu ON cu.ID = c.userid 
       LEFT JOIN ".$wpdb->prefix."project_replies AS r ON r.cid = c.commentid 
       LEFT JOIN ".$wpdb->prefix."users  AS ru ON ru.ID = r.uid 
       WHERE c.projectid = $projectid 
       ORDER BY c.commentid DESC, r.id DESC"; 

Mặc dù điều này thực sự hiệu quả (và đủ để tôi đánh dấu câu hỏi đó là đã trả lời), khi đưa vào thực tế, tôi đã gặp nhiều khó khăn. Trước tiên, việc này lấy tất cả dữ liệu dưới dạng các hàng riêng biệt có nghĩa là nếu tôi có 5 nhận xét với 3 câu trả lời, tôi thực sự nhận được 15 hàng trả về chứ không phải đối tượng dữ liệu lồng nhau với các câu trả lời được lồng trong mỗi hàng nhận xét.

Để giải quyết vấn đề này, tôi đã cố gắng một số thao tác mảng như:

$old_id=NULL; 
$comments=array(); 

foreach($getcomments as $c){ 

    if($c->commentid !== $old_id){ 

     $comments[$old_id] = $c; 
     $old_id = $c->commentid; 

    } 


    $comments[$old_id]['replies'][] = $c; 


} 

Việc làm này mang lại cho tôi một đối tượng dữ liệu lồng nhau theo yêu cầu.Tuy nhiên, nó không bao gồm truy vấn đếm trả lời và nó không giới hạn mỗi bộ trả lời thành 2 như dự định, nó truy lục tất cả chúng.

Và cuối cùng với mã thế hệ html hiện tại của tôi trong vòng foreach:

foreach($comments){ 

    //generate comment html 

    foreach($replies) { 

     //generate replies html 

    } 

} 

tôi dường như không thể có được nó để làm việc một cách chính xác với các đối tượng dữ liệu lồng nhau. Truy cập các câu trả lời sâu chính xác dường như khiến tôi bối rối. Vì vậy, để tóm tắt, tôi muốn có thể xóa các truy vấn lặp lại, kết hợp chúng thành một truy vấn lớn và hiệu quả hơn hoặc tệ nhất trong truy vấn dữ liệu và truy vấn đếm riêng, sau đó tạo đối tượng dữ liệu lồng nhau gọn gàng, với các nhận xét dưới dạng hàng và bất kỳ câu trả lời nào được lồng vào bên dưới tiêu đề 'trả lời'

Sau đó, tôi cần có khả năng lặp qua các mã này một cách chính xác trong mã php của mình để tạo html bắt buộc.

Tôi xin lỗi về độ dài của câu hỏi này và nhận ra rằng nó có thể khiến nhiều bạn trả lời, Nhưng tôi đã chiến đấu với điều này trong 19 giờ liền và thực sự cần sự giúp đỡ.

Rất cám ơn bất kỳ ai đề xuất bất kỳ đề xuất nào.

+0

Có lẽ chỉ cần thêm bảng của bạn với dữ liệu ví dụ và bảng kết quả bạn mong đợi sẽ trở nên hữu ích hơn. –

+0

Khá có thể Mosty, lấy điểm. Nếu tôi không vội vàng như tôi có một ổ đĩa 2 giờ trước tôi bắt đầu 10 phút, tôi sẽ chỉnh sửa câu hỏi như bạn đã đề xuất. – gordyr

+0

Điều này đã được đề cập một vài lần, bao gồm bài viết này: http://stackoverflow.com/questions/317322/optimized-sql-for-tree-structures – crafter

Trả lời

2

Nếu bạn muốn giữ các ý kiến ​​và trả lời trong hai bảng khác nhau (xem bình luận crafter của), bạn có thể loại bỏ các vòng lặp với một thủ thuật đơn giản: Thu thập các ID bình luận từ các truy vấn đầu tiên và sử dụng một

WHERE (cid IN (1,2,3,4, ...))

thay vì vòng lặp. Nếu bạn cần giới hạn các câu trả lời cho mỗi nhận xét, điều đó có thể xảy ra với các mệnh đề WHERE- hoặc HAVING bổ sung.

BurninLeo

+0

Cảm ơn BurninLeo. Trong khi điều này đã đi một chặng đường dài hướng tới việc bắt đầu tôi, tôi muốn để câu hỏi mở lâu hơn một chút để hy vọng đạt được thêm một số phản hồi/giải pháp. Tôi hy vọng bạn hiểu. – gordyr

+0

Tôi thậm chí không chắc chắn nếu điều này thực sự là những gì bạn cần;) Tôi cũng quan tâm đến các ý kiến ​​khác. Ngay sau khi tôi tìm thấy một số thời gian, tôi cũng sẽ đọc phần giới thiệu về các bộ lồng nhau được liên kết trong chuỗi được liên kết trong các nhận xét cho câu hỏi của bạn ... – BurninLeo

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