2

Webページに、いくつかの画像コレクションを表示しています(各コレクションのサムネイルを表示しています)。各写真には、5つの関連する表があります。

いいね(id、user_id、picture_id)、
ビュー(id、user_id、picture_id)、
コメント(id、user_id、picture_id、comment)、

pictures(id(前の表の「picture_id」に等しい)、collection_id、picture_urlおよび他のいくつかの列)、
コレクション(id(前の表のcollection_idに等しい)、および他のいくつかの列。

ページを読み込むときは、各コレクションの下にあるすべての写真のいいね、ビュー、コメントの数を集計して、それらの数を表示する必要があります。

つまり、基本的には、各写真のいいねを数え、すべてを数え、番号を表示します。各画像のビューを数え、それらをすべて数え、数を表示します。各写真のコメントを数え、それらをすべて数え、番号を表示します。そして、すすぎ、すべてのコレクションに対して繰り返します。

私はmysqlにかなり慣れていないので、選択、複数の結合、カウント、phpとmysqlなどの間で苦労しています。これを行うには非常に非効率的な方法がたくさんあると確信しているので、期待しています。これを行うための最良/最速/最も効率的な方法を教えてください。

前もって感謝します!

4

2 に答える 2

3

これは、選択と左結合で解決できます。

ごとに各テーブルのエントリをカウントするためpictureIdpicturesテーブルは各リレーションの左側になります。それで:

select 
    p.id as pictureId,
    count(distinct l.id) as count_likes,
    count(distinct v.id) as count_views,
    count(distinct c.id) as count_comments
from
    pictures as p
    left join likes as l on p.id = l.pictureId
    left join views as v on p.id = v.pictureId
    left join comments as c on p.id = c.pictureId
group by
    p.id

基本的に、テーブル内の各レコードについて、各テーブル内のすべてのレコードをカウントしていpicturesます。likesviewsまたはにレコードがない場合comments、カウントはそれぞれゼロになります。

もちろん、このアイデアをコレクションに拡張することもできます。

select
    c.id as collection_id,
    p.id as picture_id,
    count(distinct l.id) as count_likes,
    count(distinct v.id) as count_views,
    count(distinct c.id) as count_comments
from
    collections as c
    left join pictures as p on c.id = p.collection_id
    left join likes as l on p.id = l.picture_Id
    left join views as v on p.id = v.picture_Id
    left join comments as c on p.id = c.picture_Id
group by
    c.id,
    p.id

コレクションごとに結果をフィルタリングする場合は、where c.id = aValue前に追加するだけで済みます(取得するコレクションIDはgroup byどこにありますか)。aValue

これがお役に立てば幸いです。


各コレクションの集計データのみが必要な場合:

select
    c.id as collection_id,
    count(distinct l.id) as count_likes,
    count(distinct v.id) as count_views,
    count(distinct c.id) as count_comments
from
    collections as c
    left join pictures as p on c.id = p.collection_id
    left join likes as l on p.id = l.picture_Id
    left join views as v on p.id = v.picture_Id
    left join comments as c on p.id = c.picture_Id
group by
    c.id

これでうまくいくはずです;-)

于 2013-01-08T08:04:06.327 に答える
0

これは、副選択で行うことができます。

SELECT
  collections.*,
  ( SELECT COUNT(*) FROM pictures, likes
    WHERE pictures.id = likes.picture_id
      AND pictures.collection_id = collection.id
  ) AS like_count,
  ( SELECT COUNT(*) FROM pictures, views
    WHERE pictures.id = views.picture_id
      AND pictures.collection_id = collection.id
  ) AS view_count,
  ( SELECT COUNT(*) FROM pictures, comments
    WHERE pictures.id = comments.picture_id
      AND pictures.collection_id = collection.id
  ) AS comment_count
FROM collections
WHERE ...

これはテーブルを3回超えているように見えpicturesますが、MySQLは結合バッファーを使用してそれを最適化できる可能性があると思います。ただし、このクエリは実際にはテストしていないことに注意してください。また、これがパフォーマンス面でBarrankaのLEFT JOINソリューションとどのように比較されるのかもわかりません。(どちらも素朴に実装するとかなり恐ろしいので、それぞれの場合にMySQLのクエリオプティマイザがどれほど賢いかにかかっています。)

于 2013-01-08T08:06:03.827 に答える