sql >> データベース >  >> RDS >> Mysql

MYSQLクエリ-投稿に関連する最新のコメントを取得します

    このエラーメッセージ

    通常、列とテーブルの定義が原因です。これは通常、等号の両側に異なる照合があることを意味します。あなたがする必要があるのは、1つを選択し、その決定をクエリに含めることです。

    ここでの照合の問題は、@prev_valueのCROSSJOINにあり、明示的な照合を使用する必要がありました。

    また、「row_number」ロジックを単一のクロス結合に少し変更し、ifロジックを選択リストの両端に移動しました。

    いくつかのサンプルデータを以下に示します。でクエリをテストするには、サンプルデータが必要です。実用的な例であなたの質問に答えようとする人は誰でもデータを必要とします。ここに含める理由は2つあります。

    1. 私が提示する結果を理解できるように
    2. 将来、別のSQL関連の質問をするときに、データを提供することの重要性を理解できるようにします。あなたがこれをすることは私たちにとってより便利なだけではありません。質問者がサンプルデータを提供する場合、質問者はすでにそれを理解しています。これは、支援に時間を費やしている見知らぬ人の発明ではありません。

    サンプルデータ

    一部の列がテーブルから欠落していることに注意してください。テーブルの詳細で指定された列のみが含まれています。

    このサンプルデータには、1つの投稿に対して5つのコメントがあります(いいねは記録されません)

    CREATE TABLE Posts 
    (
    `id` int, 
    `uuid` varchar(7) collate utf8_unicode_ci,
    `imageLink` varchar(9) collate utf8_unicode_ci, 
    `date` datetime
     );
        
    INSERT INTO Posts(`id`, `uuid`, `imageLink`, `date`)
    VALUES
    (145, 'abcdefg', 'blah blah', '2016-10-10 00:00:00') ;
    
    CREATE TABLE   USERS
    (
    `id` int, 
    `username` varchar(15) collate utf8_unicode_ci,
     `profileImage` varchar(12) collate utf8_unicode_ci,
     `date` datetime
    ) ;
            
    INSERT INTO     USERS(`id`, `username`, `profileImage`, `date`)
    VALUES
    (145, 'used_by_already', 'blah de blah', '2014-01-03 00:00:00') ;
        
        
    CREATE TABLE Activity
    (
    `id` int, 
    `uuid` varchar(4) collate utf8_unicode_ci, 
    `uuidPost` varchar(7) collate utf8_unicode_ci,
     `type` varchar(40) collate utf8_unicode_ci, 
    `commentText` varchar(11) collate utf8_unicode_ci, `date` datetime
    ) ;
            
    INSERT INTO Activity (`id`, `uuid`, `uuidPost`, `type`, `commentText`, `date`)
     VALUES
    (345, 'a100', 'abcdefg', 'comment', 'lah lha ha', '2016-07-05 00:00:00'),
    (456, 'a101', 'abcdefg', 'comment', 'lah lah lah', '2016-07-06 00:00:00'),
    (567, 'a102', 'abcdefg', 'comment', 'lha lha ha', '2016-07-07 00:00:00'),
    (678, 'a103', 'abcdefg', 'comment', 'ha lah lah', '2016-07-08 00:00:00'),
    (789, 'a104', 'abcdefg', 'comment', 'hla lah lah', '2016-07-09 00:00:00') ;
    

    [SQL標準の動作:投稿クエリごとに2行]

    これは私の最初のクエリでしたが、いくつか修正が加えられました。結果を表示するときにコメント関連のデータが簡単に表示されるように、選択リストの列の順序を変更しました。クエリが何をするかを理解できるように、提供された結果を調べてください。 #で始まる列は、すでに述べた理由により、使用しているサンプルデータに存在しません。

    SELECT
          Posts.id
        , Posts.uuid
        , rcom.uuidPost
        , rcom.commentText
        , rcom.`date` commentDate 
        #, Posts.caption
        #, Posts.path
        , Posts.`date`
        , USERS.id
        , USERS.username
        #, USERS.fullname
        , USERS.profileImage
        , COALESCE(A.LikeCNT, 0) num_likes
    FROM Posts
    INNER JOIN USERS ON Posts.id = 145
                AND USERS.id = 145
    LEFT JOIN (
              SELECT
                    COUNT(A.uuidPost) LikeCNT
                  , A.UUIDPost
              FROM Activity A
              WHERE type = 'like'
              GROUP BY
                    A.UUIDPOST
              ) A ON A.UUIDPost = Posts.uuid 
    LEFT JOIN (
          SELECT
                @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
              , commentText
              , uuidPost
              , `date`
              , @prev_value := UUIDPOST
          FROM Activity
          CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci  ) xy
          WHERE type = 'comment'
          ORDER BY
                uuidPost
              , `date` DESC
          ) rcom ON rcom.uuidPost  = Posts.UUID
                AND rcom.row_number <= 2
    ORDER BY
          posts.`date` DESC
          ;
          
          
    

    SQLFiddleでこのクエリの実際のデモをご覧ください

    結果

    |  id |    uuid | uuidPost | commentText |                   date |                      date |  id |        username | profileImage | num_likes |
    |-----|---------|----------|-------------|------------------------|---------------------------|-----|-----------------|--------------|-----------|
    | 145 | abcdefg |  abcdefg | hla lah lah | July, 09 2016 00:00:00 | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |
    | 145 | abcdefg |  abcdefg |  ha lah lah | July, 08 2016 00:00:00 | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |
    

    予想通り、2つの行があります。最新のコメント用の1つの行と、次の最新のコメント用の別の行。これはSQLの通常の動作であり、この回答の下にコメントが追加されるまで、質問の読者はこの通常の動作が許容できると想定していました。

    質問には、明確に表現された「期待される結果」が欠けています。

    [オプション1:投稿クエリごとに1行、最大2つのコメント、列を追加]

    以下のコメントで、投稿ごとに2行が必要ないことが明らかになりました。これは、簡単な修正になります。それは簡単なことですが、オプションがあり、オプションは要件の形でユーザーによって決定されます。質問に「期待される結果」があった場合、どのオプションを選択するかがわかります。それにもかかわらず、ここに1つのオプションがあります

    SELECT
          Posts.id
        , Posts.uuid
        , max(case when rcom.row_number = 1 then rcom.commentText end) Comment_one
        , max(case when rcom.row_number = 2 then rcom.commentText end) Comment_two
        #, Posts.caption
        #, Posts.path
        , Posts.`date`
        , USERS.id
        , USERS.username
        #, USERS.fullname
        , USERS.profileImage
        , COALESCE(A.LikeCNT, 0) num_likes
    FROM Posts
    INNER JOIN USERS ON Posts.id = 145
                AND USERS.id = 145
    LEFT JOIN (
              SELECT
                    COUNT(A.uuidPost) LikeCNT
                  , A.UUIDPost
              FROM Activity A
              WHERE type = 'like'
              GROUP BY
                    A.UUIDPOST
              ) A ON A.UUIDPost = Posts.uuid 
    LEFT JOIN (
          SELECT
                @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
              , commentText
              , uuidPost
              , `date`
              , @prev_value := UUIDPOST
          FROM Activity
          CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci  ) xy
          WHERE type = 'comment'
          ORDER BY
                uuidPost
              , `date` DESC
          ) rcom ON rcom.uuidPost  = Posts.UUID
                AND rcom.row_number <= 2
    GROUP BY
          Posts.id
        , Posts.uuid
        #, Posts.caption
        #, Posts.path
        , Posts.`date`
        , USERS.id
        , USERS.username
        #, USERS.fullname
        , USERS.profileImage
        , COALESCE(A.LikeCNT, 0)
    ORDER BY
          posts.`date` DESC
          ;
    

    SQLFiddleで機能する2番目のクエリを参照

    クエリ2の結果

    |  id |    uuid | Comment_one | Comment_two |                      date |  id |        username | profileImage | num_likes |
    |-----|---------|-------------|-------------|---------------------------|-----|-----------------|--------------|-----------|
    | 145 | abcdefg | hla lah lah |  ha lah lah | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |
    

    **オプション2、最新のコメントを1つのコンマ区切りリストに連結します**

    SELECT
          Posts.id
        , Posts.uuid
        , group_concat(rcom.commentText) Comments_two_concatenated
        #, Posts.caption
        #, Posts.path
        , Posts.`date`
        , USERS.id
        , USERS.username
        #, USERS.fullname
        , USERS.profileImage
        , COALESCE(A.LikeCNT, 0) num_likes
    FROM Posts
    INNER JOIN USERS ON Posts.id = 145
                AND USERS.id = 145
    LEFT JOIN (
              SELECT
                    COUNT(A.uuidPost) LikeCNT
                  , A.UUIDPost
              FROM Activity A
              WHERE type = 'like'
              GROUP BY
                    A.UUIDPOST
              ) A ON A.UUIDPost = Posts.uuid 
    LEFT JOIN (
          SELECT
                @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
              , commentText
              , uuidPost
              , `date`
              , @prev_value := UUIDPOST
          FROM Activity
          CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci  ) xy
          WHERE type = 'comment'
          ORDER BY
                uuidPost
              , `date` DESC
          ) rcom ON rcom.uuidPost  = Posts.UUID
                AND rcom.row_number <= 2
    GROUP BY
          Posts.id
        , Posts.uuid
        #, Posts.caption
        #, Posts.path
        , Posts.`date`
        , USERS.id
        , USERS.username
        #, USERS.fullname
        , USERS.profileImage
        , COALESCE(A.LikeCNT, 0)
    ORDER BY
          posts.`date` DESC
          
    

    SQLFiddleで機能するこの3番目のクエリを参照してください

    クエリ3の結果

    |  id |    uuid | Comments_two_concatenated |                      date |  id |        username | profileImage | num_likes |
    |-----|---------|---------------------------|---------------------------|-----|-----------------|--------------|-----------|
    | 145 | abcdefg |    hla lah lah,ha lah lah | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |
    

    **まとめ**

    3つのクエリを提示しました。各クエリには、最新の2つのコメントのみが表示されますが、クエリごとに異なる方法で表示されます。最初のクエリ(デフォルトの動作)では、投稿ごとに2行が表示されます。オプション2は列を追加しますが、2番目の行を削除します。オプション3は、最新の2つのコメントを連結します。

    注意してください:

    • 質問には、すべての列をカバーするテーブル定義がありません
    • 質問にはサンプルデータがないため、ここに示されている結果を理解するのは難しくなりますが、ソリューションを準備するのも難しくなります
    • この質問には、明確な「期待される結果」(必要な出力)も欠けているため、回答がさらに複雑になっています。

    追加で提供された情報がある程度役立つことを願っています。また、SQLがデータを複数の行として表示するのは正常であることもご存知でしょう。通常の動作を望まない場合は、質問で本当に必要なことを具体的に説明してください。

    追記。 「フォロー」のさらに別のサブクエリを含めるには、既存のサブクエリと同様のサブクエリを使用できます。そのサブクエリの前または後に追加できます。 sqlfiddle こちら でも使用されていることがわかります。

    LEFT JOIN (
              SELECT
                    COUNT(*) FollowCNT
                  , IdOtherUser
              FROM Activity
              WHERE type = 'Follow'
              GROUP BY
                    IdOtherUser
              ) F ON USERS.id = F.IdOtherUser
    

    別のサブクエリを追加すると、より多くの情報が必要になる場合がありますが、データの増加に比例してクエリ全体の速度が低下する場合があります。本当に必要な機能が決まったら、それらのテーブルに必要なインデックスを検討する価値があるかもしれません。 (個別にアドバイスを求めることをお勧めします。その場合は、1。テーブルの完全なDDLと2.クエリの説明プランを含めるようにしてください。)



    1. グループ化された現在の合計のための最良のアプローチ

    2. Ajax、JQueryhtmlテーブルの並べ替え

    3. パーティションがSQLServer(T-SQL)で圧縮されているかどうかを確認する

    4. PostgreSQL:psqlコマンドを使用してPostgresインスタンスにリモート接続する