2011-04-20 24 views
5

Ben Aşağıdaki tablolarda:Sayma sayısı:

post (id, title, content) etc 
author (id, username) etc 
author_vote (post_id, author_id, value) 

değer olabilir, ya bir tiny_int 1 ya da -1.

Her yazı için pozitif ve negatif oy sayısını saymak istiyor

:

$posts = sql_select($link, "SELECT post.*, author.username 
          FROM post, author 
          AND author.id = post.author_id"); 

Neden Aşağıdaki kod çalışmıyor?

foreach ($posts as &$post) 
{ 
    $id = $post['id']; 
    $post['positive'] = (int)sql_select($link, "SELECT SUM(value) FROM author_vote WHERE post_id = $id 
              AND value = 1"); 
    $post['negative'] = (int)abs(sql_select($link, "SELECT SUM(value) FROM author_vote WHERE post_id = $id 
               AND value = -1")); 
} 

Ayrıca veritabanı birden sorgulamak zorunda kalmadan bunu yapmak için herhangi bir yol yoktur: Ben de şunları denedim

array_walk($posts, function(&$post, $link){ 
    $post['positive'] = sql_select($link, "SELECT SUM(value) FROM author_vote WHERE post_id = $post['id'] 
              AND value = 1"); 

    $post['negative'] = abs(sql_select($link, "SELECT SUM(value) FROM author_vote WHERE post_id = $post['id'] 
              AND value = -1")); 
}); 

, bu her bir yayın için aynı olması tüm oy neden olur her gönderi için kaç kez? Sürekli olarak değişmekte olan bir şey nasıl olurdu (mem) önbelleğe alınır?

+0

Ne sql yapar _select' geri dönüyor? Bu işlev için belge var mı? – webbiedave

+0

Mevcut SQL'inizde SUM kullanıyorsunuz, aslında daha hızlı sonuç veren COUNT kullanabilirsiniz. –

+0

sql_select kendim yaptığım bir işlevdir, sql sorgusu yanlışsa bir istisna atar (yani seçimi gerçekleştiremez) – jonnnnnnnnnie

cevap

5

:

Select Sum(Case When value < 0 Then 1 Else 0 End) As NegVotes 
    , Sum(Case When value > 0 Then 1 Else 0 End) As PosVotes 
From author_vote 
Where post_id = ... 

Eğer gönderim başına olumlu ve olumsuz oy isterseniz: Eğer ilk sorguyu birleştirmek istiyorsa

Select post_id 
    , Sum(Case When value < 0 Then 1 Else 0 End) As NegVotes 
    , Sum(Case When value > 0 Then 1 Else 0 End) As PosVotes 
From author_vote 
Group By post_id 

ve ikinci sorgu alabilirsiniz:

Select post.... 
    , author.username 
    , Coalesce(post_count.NegVotes,0) As NegVotes 
    , Coalesce(post_count.PosVotes,0) As PosVotes 
From post 
    Join author 
     On author.id = post.author_id 
    Left Join (
       Select post_id 
        , Sum(Case When value < 0 Then 1 Else 0 End) As NegVotes 
        , Sum(Case When value > 0 Then 1 Else 0 End) As PosVotes 
       From author_vote 
       Group By post_id 
       ) As post_count 
     On post_count.post_id = post.post_id 
+0

Bunu ilk sorgu ile nasıl birleştirirsiniz? Böylece, her gönderiyle ilişkili tüm yayınları ve oyları seçebilirim. – jonnnnnnnnnie

+0

@jonnnnnnnnnie - Bu sorguyu türetilmiş bir tabloya yazmanız yeterlidir. Gösterimi göstermek için cevabımı genişlettim. – Thomas

0

Kullandığınız sql_select() işlevini bulamıyorum, ancak sum() yerine SQL'inizde count(*)'u kullanmaktan daha iyi olabilirsiniz. Sadece görünen satırları saymanız gerekir, değerleri değil. Ayrıca, küçük bir meraklısı alabilir ve GROUP BY:

Her bir benzersiz değer için bir satır döndürür. Döndürülen her satır, bu değeri kullanarak benzersiz değeri ve satır sayısını bildirir.

Tek bir sorgu içinde sayımı yapabileceği