Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

MYSQL Query - Dapatkan komentar terbaru terkait dengan posting

Pesan kesalahan ini

biasanya karena definisi kolom dan tabel Anda. Ini biasanya berarti bahwa di kedua sisi tanda sama dengan ada susunan yang berbeda. Yang perlu Anda lakukan adalah memilih salah satu dan menyertakan keputusan itu dalam kueri Anda.

Masalah susunan di sini adalah di CROSS JOIN dari @prev_value yang membutuhkan susunan eksplisit untuk digunakan.

Saya juga sedikit mengubah logika "row_number" menjadi gabungan silang tunggal dan memindahkan logika if ke ekstrem daftar pilih.

Beberapa contoh data ditampilkan di bawah ini. Data sampel diperlukan untuk menguji kueri dengan. Siapa pun yang mencoba menjawab pertanyaan Anda dengan contoh kerja akan membutuhkan data. Alasan saya memasukkannya ada dua.

  1. agar Anda mengerti setiap hasil yang saya sajikan
  2. sehingga di masa mendatang ketika Anda mengajukan pertanyaan terkait SQL lainnya, Anda memahami pentingnya menyediakan data. Tidak hanya lebih nyaman bagi kami bahwa Anda melakukan ini. Jika penanya memberikan contoh data, maka penanya akan memahaminya - ini bukan penemuan orang asing yang telah mencurahkan sebagian waktunya untuk membantu.

Contoh Data

Harap perhatikan beberapa kolom hilang dari tabel, hanya kolom yang ditentukan dalam detail tabel yang disertakan.

Data sampel ini memiliki 5 komentar terhadap satu postingan (tidak ada suka yang dicatat)

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') ;

[Perilaku Standar SQL:2 baris per kueri Posting]

Ini adalah pertanyaan awal saya, dengan beberapa koreksi. Saya mengubah urutan kolom daftar pilih sehingga Anda akan melihat beberapa data terkait komentar dengan mudah ketika saya mempresentasikan hasilnya. Harap pelajari hasil yang disediakan sehingga Anda dapat memahami apa yang akan dilakukan kueri. Kolom yang didahului dengan # tidak ada dalam data sampel yang saya kerjakan karena alasan yang telah saya catat.

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
      ;
      
      

Lihat demonstrasi kerja kueri ini di SQLFiddle

Hasil :

|  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 |

Ada 2 BARIS - seperti yang diharapkan. Satu baris untuk komentar terbaru, dan baris lain untuk komentar terbaru berikutnya. Ini adalah perilaku normal untuk SQL dan hingga komentar ditambahkan di bawah jawaban ini, pembaca pertanyaan akan menganggap perilaku normal ini dapat diterima.

Pertanyaannya tidak memiliki "hasil yang diharapkan" yang diartikulasikan dengan jelas.

[Opsi 1:Satu baris per kueri Posting, dengan HINGGA 2 komentar, kolom ditambahkan]

Dalam komentar di bawah ini terungkap bahwa Anda tidak ingin 2 baris per posting dan ini akan menjadi perbaikan yang mudah. Yah itu agak mudah TAPI ada opsi dan opsi ditentukan oleh pengguna dalam bentuk persyaratan. JIKA pertanyaannya memiliki "hasil yang diharapkan" maka kita akan tahu opsi mana yang harus dipilih. Meskipun demikian, inilah satu opsi

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
      ;

Lihat kueri kedua yang berfungsi di SQLFiddle

Hasil kueri 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 |

** Opsi 2, gabungkan komentar terbaru ke dalam satu daftar yang dipisahkan koma **

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
      

Lihat kueri ketiga ini berfungsi di SQLFiddle

Hasil kueri 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 |

** Ringkasan **

Saya telah menyajikan 3 kueri, masing-masing hanya menampilkan 2 komentar terbaru, tetapi setiap kueri melakukannya dengan cara yang berbeda. Kueri pertama (perilaku default) akan menampilkan 2 baris untuk setiap posting. Opsi 2 menambahkan kolom tetapi menghapus baris kedua. Opsi 3 menggabungkan 2 komentar terbaru.

Harap diperhatikan bahwa:

  • Pertanyaan tidak memiliki definisi tabel yang mencakup semua kolom
  • Pertanyaan tidak memiliki sampel data, yang mempersulit Anda untuk memahami hasil apa pun yang disajikan di sini, tetapi juga lebih sulit bagi kami untuk menyiapkan solusi
  • Pertanyaan juga tidak memiliki "hasil yang diharapkan" yang pasti (keluaran yang diinginkan) dan ini menyebabkan kerumitan lebih lanjut dalam menjawab

Saya berharap informasi tambahan yang diberikan akan berguna, dan sekarang Anda juga tahu bahwa SQL menyajikan data sebagai beberapa baris adalah hal yang normal. Jika Anda tidak menginginkan perilaku normal tersebut, harap jelaskan apa yang sebenarnya Anda inginkan dalam pertanyaan Anda.

Nota bene. Untuk memasukkan subkueri lain untuk "mengikuti", Anda dapat menggunakan subkueri serupa dengan yang sudah Anda miliki. Itu dapat ditambahkan sebelum atau sesudah subquery itu. Anda juga dapat melihatnya digunakan di sqlfiddle di sini

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

Sementara menambahkan subkueri lain dapat menyelesaikan keinginan Anda untuk informasi lebih lanjut, kueri keseluruhan mungkin menjadi lebih lambat sebanding dengan pertumbuhan data Anda. Setelah Anda menentukan fungsionalitas yang benar-benar Anda butuhkan, mungkin ada baiknya mempertimbangkan indeks apa yang Anda butuhkan pada tabel tersebut. (Saya yakin Anda akan disarankan untuk meminta saran itu secara terpisah, dan jika Anda memastikan Anda menyertakan 1. DDL lengkap tabel Anda dan 2. rencana penjelasan kueri.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PDO melempar kesalahan jika MYSQL_ATTR_INIT_COMMAND digunakan

  2. PHP &MySQL Termasuk tombol Hapus di halaman yang sama

  3. MySQL GROUP oleh Regex?

  4. apakah baik menyimpan nilai desimal sebagai varchar di mysql?

  5. MySQL:ALTER IGNORE TABLE TAMBAHKAN UNIK, apa yang akan dipotong?