2016-11-08 3 views
0

私はしばらくの間、カスタムフォーラムに取り組んでいます。私はフォーラムから最近の投稿を表示したいと思います。私は私のUbuntuサーバーでPHP 7.0.8とMySQL 5.7.16を使用しています。なぜSQLクエリはタイムスタンプ順に左結合データを出力しないのですか?

フォーラムのデータがで収集された2つのテーブルがあります。 uap4_forum_postsとuap4_forum_post_replies

トピックがuap4_forum_postsに保存されます。 トピックの返信はuap4_forum_post_repliesに保存されます。

すべての新しいトピックとすべてのトピック返信を取得し、タイムスタンプで並べ替えることを目標にしています。私は日付でトピックを並べ替えるのに問題はありませんが、トピックの返信を追加すると、最初のトピックの返信のみが使用されます。したがって、複数のトピック返信がある場合、最新のものは表示されません。

次のように私のデータベースがセットアップされている: uap4_forum_posts enter image description here ここuap4_forum_post_replies enter image description here

は、私がこれまで持っているMySQLのクエリです:ここで

SELECT sub.* FROM (
    SELECT 
     fp.forum_post_id as forum_post_id, fp.forum_id as forum_id, 
     fp.forum_user_id as forum_user_id, fp.forum_title as forum_title, 
     fp.forum_edit_date as forum_edit_date, 
     fp.forum_timestamp as forum_timestamp, fpr.id as id, 
     fpr.fpr_post_id as fpr_post_id, fpr.fpr_id as fpr_id, 
     fpr.fpr_user_id as fpr_user_id, fpr.fpr_title as fpr_title, 
     fpr.fpr_edit_date as fpr_edit_date, 
     fpr.fpr_timestamp as fpr_timestamp, 
     GREATEST(fp.forum_timestamp, COALESCE(fpr.fpr_timestamp, '00-00-00 00:00:00')) AS tstamp 
     FROM uap4_forum_posts fp 
     LEFT JOIN uap4_forum_post_replies fpr 
     ON fp.forum_post_id = fpr.fpr_post_id 
     WHERE fp.allow = 'TRUE' 
) sub 
GROUP BY forum_post_id 
ORDER BY tstamp DESC 

は、上記のクエリとの結果である: enter image description here

2016-11-08 1 3:36:46上記のデータを持つ最新のタイムスタンプでなければなりません。

ありがとうございました。これは私が取り組んでいるフリー・オープンソース・プロジェクトのためのものです。

答えて

1

代わりにこれを試してくださいそれは一般的な「落ち着き」です。

ORDER BYの操作は、GROUP BYの操作の後にになることに注意してください。

MySQL以外のデータベースでは、「GROUP BY句ではないSELECTリストの非集計式」の行に沿って、クエリにエラーが発生します。

非標準のMySQL拡張ではクエリを実行できますが、SELECTリストの式の一部に返される値はで、不確定のです。値はグループのいくつかの行からのものですが、グループ内の最新のもの、最も早いもの、最も低いもの、または特定の行のものであるという保証はありません。

参考:あなたのクエリによって返さhttps://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html

結果は文書化の挙動と一致しています。


この質問は以前に何度も聞かれました。私たちは、各fpr_post_idのための "最新" fpr_timestampを得ることができ

... (fpr_post_id,fpr_timestamp)タプルがusp4_forum_post_repliesユニークある場合はSO

フォロー

[mysql] group by wrong results 

を検索お勧めします次のようなクエリを使用します:

SELECT mr.fpr_post_id 
     , MAX(mr.fpr_timestamp) AS max_fpr_timestamp 
    FROM uap4_forum_post_replies mr 
    GROUP BY mr.fpr_post_id 

(最高のパフォーマンスを得るために、わかりやすい表のために、適切なインデックスを用意する必要があります。

... ON uap4_forum_post_replies (fpr_post_id,fpr_timestamp) 

(その順序で先頭の列として、これら2列の任意の指標、。)


次に我々は、行ソースとして、インライン・ビューとしてそのクエリを使用することができ別のクエリ。たとえば:これにより

SELECT fp.forum_post_id  AS forum_post_id 
     , fp.forum_id   AS forum_id 
     , fp.forum_user_id  AS forum_user_id 
     , fp.forum_title  AS forum_title 
     , fp.forum_edit_date AS forum_edit_date 
     , fp.forum_timestamp AS forum_timestamp 
     , fpr.id    AS id 
     , fpr.fpr_post_id  AS fpr_post_id 
     , fpr.fpr_id   AS fpr_id 
     , fpr.fpr_user_id  AS fpr_user_id 
     , fpr.fpr_title  AS fpr_title 
     , fpr.fpr_edit_date AS fpr_edit_date 
     , fpr.fpr_timestamp AS fpr_timestamp 
     , GREATEST(fp.forum_timestamp,COALESCE(fpr.fpr_timestamp,'0000-00-00 00:00:00')) 
            AS tstamp 
    FROM uap4_forum_posts fp 
    LEFT 
    JOIN (-- latest fpr_timestamp for each post 
      SELECT mr.fpr_post_id 
       , MAX(mr.fpr_timestamp) AS max_fpr_timestamp 
      FROM uap4_forum_post_replies mr 
      GROUP BY mr.fpr_post_id 
     ) lr 
    LEFT 
    JOIN uap4_forum_post_replies fpr 
     ON fpr.fpr_post_id = lr.fpr_post_id 
    AND fpr.fpr_timestamp = lr.max_fpr_timestamp 
    WHERE fp.allow = 'TRUE' 
    ORDER BY tstamp DESC 

、我々は各fpr_post_idため、マッチングfpr_timestampでのみ行を取得するために、最新のfpr_timestampを使用しています。

fpr_post_idに重複するfpr_timestampの値がある場合、複数の行を返す可能性があることに注意してください。それがユニークであることが保証されていない場合、我々はこのアプローチを拡張することができます。 idが一意であると仮定すると、我々はこのようなクエリで、fpr_timestamp同じ最新で行の最大idを得ることができます:

SELECT xr.fpr_post_id 
     , MAX(xr.id) AS max_id 
    FROM (SELECT mr.fpr_post_id 
       , MAX(mr.fpr_timestamp) AS max_fpr_timestamp 
      FROM uap4_forum_post_replies mr 
      GROUP BY mr.fpr_post_id 
     ) lr 
    JOIN uap4_forum_post_replies xr 
     ON xr.fpr_post_id = lr.fpr_post_id 
    AND xr.fpr_timestamp = lr.max_fpr_timestamp 

は、次に外側のクエリでは、我々はid列にuap4_forum_post_repliesに参加することができ、そのid値を持つ行を取得します。

これはほんの一例です。同等の結果を達成する他のクエリパターンがあります。

-1

この質問は何度も頼まれました。

SELECT 
     fp.forum_post_id as forum_post_id, fp.forum_id as forum_id, 
     fp.forum_user_id as forum_user_id, fp.forum_title as forum_title, 
     fp.forum_edit_date as forum_edit_date, 
     fp.forum_timestamp as forum_timestamp, fpr.id as id, 
     fpr.fpr_post_id as fpr_post_id, fpr.fpr_id as fpr_id, 
     fpr.fpr_user_id as fpr_user_id, fpr.fpr_title as fpr_title, 
     fpr.fpr_edit_date as fpr_edit_date, 
     fpr.fpr_timestamp as fpr_timestamp, 
     GREATEST(fp.forum_timestamp, COALESCE(fpr.fpr_timestamp, '00-00-00 00:00:00')) AS tstamp 
     FROM uap4_forum_posts fp 
     LEFT JOIN uap4_forum_post_replies fpr 
     ON fp.forum_post_id = fpr.fpr_post_id 
     WHERE fp.allow = 'TRUE' 
ORDER BY GREATEST(fp.forum_timestamp, COALESCE(fpr.fpr_timestamp, '00-00-00 00:00:00')) DESC 
+0

なぜOPは「これを試してみたいですか? 「これ」との違いは何ですか? (この答えのように私には尋ねられた質問に答えてマークを逃してしまったように見えます... "*なぜ...タイムスタンプで順序付けられていないか*"(これは提案された解決策です。 「タイムスタンプで順番に」、それもその部門のミスであるようです) – spencer7593

+0

私は機能別にグループを削除したときと同じ結果を得ました。 –

関連する問題