2

困惑して頭をかきむしる。それは本当に単純なはずですが、私はそれを見ていません。

4 つのテーブルがあるとします。

video = id
hastag = id, tag_id, video_id
hasteam = id, team_id, video_id
hasidol = id, idol_id, video_id

このデータセット (例として):

video = (1), (2), (3)
hastag = (1, 1, 1), (2, 1, 2), (3, 2, 3)
hasteam = (1, 1, 1), (2, 1, 3), (3, 2, 2)
hasidol = (1, 1, 3)

そして、このクエリ:

SELECT v.id ,
COUNT(vhtag.id),
COUNT(vhteam.id),
COUNT(vhidol.id)
FROM video v
LEFT JOIN hastag vhtag ON vhtag.video_id = v.id
LEFT JOIN hasteam vhteam ON vhteam.video_id = v.id
LEFT JOIN hasidol vhidol ON vhidol.video_id = v.id

WHERE
v.id <> 1
AND
(
  vhtag.tag_id IN (SELECT htt2.tag_id FROM hastag htt2 WHERE video_id = 1)
  OR
  vhteam.team_id IN (SELECT htt3.team_id FROM hasteam htt3 WHERE video_id = 1)
  OR
  vhidol.idol_id IN (SELECT htt4.idol_id FROM hasidol htt4 WHERE video_id = 1)
)
GROUP BY v.id

WHERE 句に対応しない "has" 行の数が表示されます。たとえば、動画の行に、動画 ID が 1 の共通のチームが 1 つだけあり、まったく関連のないタグがある場合、「共通のタグカウント: 0 (無関係なタグのため)、共通チームのカウント: 1".

ここで、次のように、クエリを 1 つの "has" テーブルのみに制限する限り、次のようになります。

SELECT v.id ,
COUNT(vhtag.id)
FROM video v
LEFT JOIN hastag vhtag ON vhtag.video_id = v.id

WHERE
v.id <> 1
AND
(
  vhtag.tag_id IN (SELECT htt2.tag_id FROM hastag htt2 WHERE video_id = 1)
)
GROUP BY v.id

それは機能しますが、問題は、複数の「has」テーブルをクエリに入れようとしたときです。HAVING を使用してみましたが、「vhtag.tag_id」列を認識しません。私は明らかにここで何か間違ったことをしています、誰かが私を助けることができますか?

編集:

この種の作品:

LEFT JOIN hastag vhtag ON vhtag.video_id = v.id AND vhtag.tag_id IN (SELECT htt2.tag_id FROM hastag htt2 WHERE video_id = 1)
LEFT JOIN hasteam vhteam ON vhteam.video_id = v.id AND vhteam.team_id IN (SELECT htt3.team_id FROM hasteam htt3 WHERE video_id = 1)
LEFT JOIN hasidol vhidol ON vhidol.video_id = v.id AND vhidol.idol_id IN (SELECT htt4.idol_id FROM hasidol htt4 WHERE video_id = 1)

そして、Doctrine でもそれを使用できます (私は愚かで、WITH を忘れていました)。これは最適な方法ですか?

4

2 に答える 2

0

たとえば、次のようにクエリを単純化してみてください-

SELECT
  v.id,
  COUNT(vhtag.id),
  COUNT(vhteam.id),
  COUNT(vhidol.id)
FROM
  video v
LEFT JOIN (SELECT * FROM hastag WHERE video_id = 1) vhtag
  ON vhtag.video_id = v.id
LEFT JOIN (SELECT * FROM hasteam WHERE video_id = 1) vhteam
  ON vhteam.video_id = v.id
LEFT JOIN (SELECT * FROM hasidol WHERE video_id = 1) vhidol
  ON vhidol.video_id = v.id
WHERE
  v.id <> 1
GROUP BY
  v.id

正しい結果が得られますか?

出力:

+------+-----------------+------------------+------------------+
| id   | COUNT(vhtag.id) | COUNT(vhteam.id) | COUNT(vhidol.id) |
+------+-----------------+------------------+------------------+
|    2 |               0 |                0 |                0 |
|    3 |               0 |                0 |                0 |
+------+-----------------+------------------+------------------+
于 2012-08-15T15:27:53.957 に答える
0

結合が各チーム内で相互結合を引き起こしているという問題があります。

最も簡単な方法は、個別のカウントを行うことです。

SELECT v.id , COUNT(distinct vhtag.id), COUNT(distinct vhteam.id),
       COUNT(distinct vhidol.id)
FROM video v LEFT JOIN
     hastag vhtag
     ON vhtag.video_id = v.id
     LEFT JOIN hasteam vhteam
     ON vhteam.video_id = v.id
     LEFT JOIN hasidol vhidol
     ON vhidol.video_id = v.id 

実際の解決策は、各値を個別に集計してから、結果を結合することです。

于 2012-08-15T15:57:13.627 に答える