2

galleryというテーブルが1つあります。ギャラリーの各行について、テーブル画像にはいくつかの行があります。1枚の写真は1つのギャラリーに属しています。次に、テーブル投票があります。各行には、特定のギャラリーの賛成票または反対票があります。(簡略化された)構造は次のとおりです。

gallery ( gallery_id )
picture ( picture_id, picture_gallery_ref )
vote ( vote_id, vote_value, vote_gallery_ref )

ここで、1つのクエリで次の情報を取得したいと思います。独自のデータフィールドを持つすべてのギャラリー、ギャラリーに接続されている写真の数、および投票の合計値。

これが私のクエリですが、複数の結合があるため、集計された値は正しいものではありません。(少なくとも、写真または投票のいずれかの行が複数ある場合。)

SELECT 
  *, SUM( vote_value ) as score, COUNT( picture_id ) AS pictures
FROM 
  gallery
LEFT JOIN 
  vote
  ON gallery_id = vote_gallery_ref
LEFT JOIN 
  picture
  ON gallery_id = picture_gallery_ref
GROUP BY gallery_id

正しい数の写真が表示されることに気付いたのでCOUNT( DISTINCT picture_id )、これを試しました。

( SUM( vote_value ) / GREATEST( COUNT( DISTINCT picture_id ), 1 ) ) AS score

この例では機能しますが、1つのクエリにさらに多くの結合がある場合はどうなりますか?

この問題を解決できる「よりエレガントな」方法があるかどうかを知りたいだけです。また、私のソリューションがMySQL固有であるか標準SQLであるかを知りたいですか?

4

4 に答える 4

5

オカムのウィリアムからのこの引用はここに適用されます。

Enita non sunt multiplicanda praeter necessitationm

(ラテン語で「実体は必要以上に増殖してはならない」)。

なぜこれを 1 回のクエリで実行する必要があるのか​​を再考する必要があります。 1 つのクエリが複数のクエリよりもオーバーヘッドが少ないのは事実ですが、その 1 つのクエリの性質が複雑になりすぎて、開発することも RDBMS を実行することもできない場合は、別のクエリを実行してください。

于 2009-02-18T20:30:22.640 に答える
3

または、サブクエリを使用するだけです...

これが有効な MySQL 構文かどうかはわかりませんが、次のようなことができるかもしれません。

SELECT
  gallery.*, a.score, b.pictures
LEFT JOIN
(
  select vote_gallery_ref, sum(vote_value) as score
  from vote
  group by vote_gallery_ref
) a ON gallery_id = vote_gallery_ref
LEFT JOIN 
(
  select picture_gallery_ref, count(picture_id) as pictures
  from picture
  group by picture_gallery_ref
) b ON gallery_id = picture_gallery_ref
于 2009-02-18T20:42:17.150 に答える
1

どのくらいの頻度で投票記録を追加/変更しますか?

どのくらいの頻度で写真の記録を追加/削除しますか?

これらの合計に対して、このクエリをどのくらいの頻度で実行しますか?

ギャラリー テーブルに合計フィールドを作成する方がよい場合があります ( total_pictures, total_votes, total_vote_values)。

ピクチャ テーブルのレコードを追加または削除すると、ギャラリー テーブルの合計も更新されます。これは、picture テーブルのトリガーを使用して、ギャラリー テーブルを自動的に更新することで実行できます。また、picture テーブルと gallery テーブルを更新する 2 つの SQL ステートメントを組み合わせたトランザクションを使用して実行することもできます。ピクチャ テーブルにレコードを追加するtotal_picturesと、ギャラリー テーブルのフィールドがインクリメントされます。ピクチャ テーブルのレコードを削除すると、total_picturesフィールドが減少します。

同様に、投票レコードが追加または削除された場合、または変更がおよびフィールドvote_valueを更新した場合も同様です。レコードを追加すると、フィールドがインクリメントされ、 に追加されます。レコードを削除すると、フィールドが減少し、から減算されます。投票レコードの更新も、差で更新する必要があり ます(古い値を減算し、新しい値を追加します)。total_votestotal_vote_valuestotal_votesvote_valuestotal_vote_valuestotal_votesvote_valuestotal_vote_valuesvote_valuestotal_vote_values

クエリは簡単になりました。ギャラリー テーブルからの単純なクエリです。しかし、これは画像と投票テーブルへのより複雑な更新を犠牲にしています。

于 2009-02-18T21:10:21.670 に答える
0

ビルカーウィンが言ったように、これをすべて1つのクエリ内で行うのはかなり醜いです。

ただし、それを行う必要がある場合は、非集計データを集計データと結合して選択するには、サブクエリに対して結合する必要があります(ここ数年、SQLをあまり使用していないため、実際にはこれの適切な用語を忘れています)。

nameギャラリーテーブルに追加のフィールドとstate:があると仮定しましょう。

select g.gallery_id, g.name, g.state, i.num_pictures, j.sum_vote_values
from gallery g
inner join (
  select g.gallery_id, count(p.picture_id) as 'num_pictures'
  from gallery g
  left join picture p on g.gallery_id = p.picture_gallery_ref
  group by g.gallery_id) as i on g.gallery_id = i.gallery_id
left join (
  select g.gallery_id, sum(v.vote_value) as 'sum_vote_values'
  from gallery g
  left join vote v on g.gallery_id = v.vote_gallery_ref
  group by g.gallery_id
) as j on g.gallery_id = j.gallery_id

これにより、次のような結果セットが生成されます。

gallery_id, name, state, num_pictures, sum_vote_values
1, 'Gallery A', 'NJ', 4, 19
2, 'Gallery B', 'NY', 3, 32
3, 'Empty gallery', 'CT', 0, 
于 2009-02-18T20:46:50.493 に答える