2009-05-23 3 views
0

私は小さなフォーラムを作成しています。MySQLのクエリ、結合、および自分自身、または私がいつも苦労する方法

SElECT... JOIN...クエリを実行しようとすると、個々の投稿の情報と最後の返信(もしあれば)が表示されます。苦労してすべてを行うために、私の欲望の一環として、これは5つのテーブル(この問題へのrevelant列のみが記載されている)

 
commentInfo referenceID | referenceType | authorID | create 
postit   id | title 
postitInfo  referencePostitID | create | authorID 
user   id | username | permission 
userInfo  referenceUserID | title 

そうをカバーして、私は最新の話題を取得するには、このクエリSELECT... JOIN...クエリを実行し、その最後の返信

SELECT DISTINCT 
    t1.id, t1.title, t2.create, t2.lastEdit, t2.authorID, t3.username, 
    t4.title AS userTitle, t3.permission, t5.create AS commentCreate, 
    t5.authorID AS commentAuthor, t6.username AS commentUsername, 
    t6.permission AS commentPermission 
FROM rantPostit AS t1 
LEFT JOIN (rantPostitInfo AS t2) 
    ON (t1.id = t2.referencePostitID) 
LEFT OUTER JOIN (rantUser as t3, rantUserInfo as t4) 
    ON (t2.authorId = t3.id AND t4.referenceUserId = t2.authorId) 
LEFT OUTER JOIN (rantCommentInfo as t5, rantUser as t6) 
    ON (t5.referenceType = 8 AND t5.referenceID = t1.id AND t6.id = t5.authorID) 
ORDER BY t2.create DESC, t5.create DESC 

これでトピックの投稿が返されます。私はそれらの2つを持っていると言う、それは両方の罰金を返します。私は最初に8つの返信があるとします。これは9つのエントリを返します(トピック+返信の場合はそれぞれ1つ、返答のない場合は1つ)。だから私は私の問題はこれだと思う:最後のLEFT OUTER JOIN句のリターンの数をちょうど最近のものに制限するか、または最も新しいものだけをウィンドウの外に打つべきかわからない。

(はい、ORDER BY...の句がうまくいきません。投稿日時、コメント作成日時順に並べ替えることができます。はい、2つのフィールドを追加することですべての問題を簡略化できますpostitInfo、lastCommentCreate、lastCommentCreateIDに入力して返信するたびに更新されますが...難しいのが好きです。)

どうしたのですか?

これは、私が薪で丸めてハンマーで叩いてしまうような、まったく問題がないのでしょうか?

答えて

1

分割、およびuseruserInfoテーブルは、難読化のものを除いてずっとここに何もしないように見えます。よりよい解決策を確認するには、のは、彼らの本質に物事を煮詰めるてみましょう:テーブルPosts(主キーidと、作成日date、および他のフィールド)主キーidと、テーブルCommentsは(、外部キーrefIdは、Posts参照します固有の作成日date、および他のフィールド)。私たちはすべての投稿を見たいと思っていますが、最新のコメントがある場合は(idのテーブル行が検索され、その他のフィールドはSELECTで文脈的に使用されていますが、コア構造を変更することはなく、コア構造に単純化することで解決策を説明することができます)。私は、コメントの作成日が一意であると仮定しています。そうでなければ、「最新のコメント」はあいまいである可能性があります(もちろん、あいまいさは任意のポストに "最新のコメント" )。

だから、ここ1つのアプローチです:

SELECT Posts.id, Comments.id FROM Posts 
LEFT OUTER JOIN Comments on (Posts.id = Comments.refId) 
WHERE Comments.create IS NULL OR (
     Comments.create = (SELECT create FROM Comments 
         WHERE refID = Posts.id 
         ORDER BY create DESC 
         LIMIT 1) 
) /* add ORDER BY &c to taste;-) */ 

アイデア:各ポストのために、私たちは「ヌルコメント」したい(それまではコメントはなされていない場合)、または他のその日付を作成しているコメント投稿を参照している人の中で最も高い。ここでは、内側のSELECTが "最も高い"作成日を見つけるのを担当します。したがって、同じ考え方では、内部選択はSELECT MAX(create) FROM Comments WHERE refID = Posts.idである可能性があります(より短くより直接的なものとして、&おそらく速い)。

+0

これはあなたにトップ1のコメントを与えますが、彼はトップ5を探していますか? – Andomar

+0

いいえ、私は一番上のものが必要です。私はそれを可能にするために5つのテーブルを使用しています(しかし、彼と一緒に、私は彼のプレゼントは2つですが、わずか3で試してみます。)LEFT OUTER JOINを作成日時に追加するのはあまり難しくない –

+0

@Nikolai Echternacht: P – Andomar

0

最後のLEFT JOINが複数の行を返すことができるように見えます。

ORDER BY t5.create DESC 
LIMIT 5 

ない場合は、非常に簡単な解決策は、別のクエリとコメント取得するには、次のようになります:

SELECT * 
FROM rantCommentInfo t5 
    ON t5.referenceType = 8 
    AND t5.referenceid = t1.id 
LEFT OUTER JOIN rantUser t6 
    ON t6.id = t5.authorID 
ORDER BY CommentCreate 
WHERE t5.referenceid = YourT1Id 
LIMIT 5 

できますそれが本当ならば、あなただけの最後の5件のコメントを取得するためにLIMIT 5を使用することができますMySQLがサポートしていないROW_NUMBERを使わずに、1つのクエリでそれを行う方法を考えています。 postpostInfo

+0

私はお詫びしますが、これは最後の返信でトピックのインデックスを表示するためです(デフォルトの制限はLimit 0,25です)。このアイデアにはメリットがあり、おそらく私がこれまでに見つけた解決策に最も近いものがあります。別のクエリを実行し、その結果を元の情報を含む配列に追加してから、 –

関連する問題