Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

MYSQL Query - Nhận bình luận mới nhất liên quan đến bài đăng

Thông báo lỗi này

thường là do định nghĩa của các cột và bảng của bạn. Nó thường có nghĩa là ở hai bên của một dấu bằng có các đối chiếu khác nhau. Những gì bạn cần làm là chọn một và đưa quyết định đó vào truy vấn của bạn.

Vấn đề đối chiếu ở đây là trong CROSS JOIN của @prev_value, cần đối chiếu rõ ràng để sử dụng.

Tôi cũng đã thay đổi một chút logic "row_number" thành một phép nối chéo duy nhất và chuyển logic if sang các cực của danh sách được chọn.

Một số dữ liệu mẫu được hiển thị bên dưới. Dữ liệu mẫu là cần thiết để kiểm tra các truy vấn với. Bất kỳ ai cố gắng trả lời câu hỏi của bạn bằng các ví dụ làm việc sẽ cần dữ liệu. Lý do tôi đưa nó vào đây gấp đôi.

  1. để bạn hiểu bất kỳ kết quả nào mà tôi trình bày
  2. để sau này khi bạn hỏi một câu hỏi liên quan đến SQL khác, bạn hiểu tầm quan trọng của việc cung cấp dữ liệu. Nó không chỉ thuận tiện hơn cho chúng tôi mà bạn làm điều này. Nếu người hỏi cung cấp dữ liệu mẫu thì người hỏi sẽ hiểu điều đó - đó không phải là phát minh của một người lạ nào đó đã dành chút thời gian của họ để giúp đỡ.

Dữ liệu mẫu

Xin lưu ý rằng một số cột bị thiếu trong bảng, chỉ những cột được chỉ định trong chi tiết bảng mới được bao gồm.

Dữ liệu mẫu này có 5 nhận xét chống lại một bài đăng (không có lượt thích nào được ghi lại)

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

[Hành vi chuẩn của SQL:2 hàng cho mỗi truy vấn bài đăng]

Đây là truy vấn ban đầu của tôi, với một số chỉnh sửa. Tôi đã thay đổi thứ tự cột của danh sách lựa chọn để bạn sẽ dễ dàng nhìn thấy một số dữ liệu liên quan đến nhận xét khi tôi trình bày kết quả. Vui lòng nghiên cứu những kết quả mà chúng được cung cấp để bạn có thể hiểu truy vấn sẽ làm gì. Các cột đứng trước # không tồn tại trong dữ liệu mẫu mà tôi đang làm việc vì những lý do tôi đã lưu ý.

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
      ;
      
      

Xem trình diễn hoạt động của truy vấn này tại SQLFiddle

Kết quả :

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

Có 2 ROWS - như mong đợi. Một hàng cho nhận xét gần đây nhất và một hàng khác cho nhận xét gần đây nhất tiếp theo. Đây là hành vi bình thường đối với SQL và cho đến khi nhận xét được thêm vào bên dưới câu trả lời này, người đọc câu hỏi sẽ cho rằng hành vi bình thường này có thể chấp nhận được.

Câu hỏi thiếu "kết quả mong đợi" được trình bày rõ ràng.

[Tùy chọn 1:Một hàng cho mỗi truy vấn Bài đăng, với LÊN TỚI 2 nhận xét, thêm cột]

Trong một bình luận bên dưới, nó đã được tiết lộ rằng bạn không muốn 2 hàng mỗi bài đăng và đây sẽ là một sửa chữa dễ dàng. Vâng, nó khá dễ dàng NHƯNG có các tùy chọn và các tùy chọn được quyết định bởi người dùng dưới dạng yêu cầu. NẾU câu hỏi có "kết quả mong đợi" thì chúng ta sẽ biết phải chọn phương án nào. Tuy nhiên, đây là một lựa chọn

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
      ;

Xem truy vấn thứ hai hoạt động tại SQLFiddle

Kết quả của truy vấn 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 |

** Tùy chọn 2, nối các nhận xét gần đây nhất vào một danh sách được phân tách bằng dấu phẩy duy nhất **

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
      

Xem truy vấn thứ ba này hoạt động tại SQLFiddle

Kết quả của truy vấn 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 |

** Tóm tắt **

Tôi đã trình bày 3 truy vấn, mỗi truy vấn chỉ hiển thị 2 nhận xét gần đây nhất, nhưng mỗi truy vấn thực hiện điều đó theo một cách khác nhau. Truy vấn đầu tiên (hành vi mặc định) sẽ hiển thị 2 hàng cho mỗi bài đăng. Tùy chọn 2 thêm một cột nhưng loại bỏ hàng thứ hai. Tùy chọn 3 nối 2 nhận xét gần đây nhất.

Xin lưu ý rằng:

  • Câu hỏi thiếu các định nghĩa bảng bao gồm tất cả các cột
  • Câu hỏi thiếu bất kỳ dữ liệu mẫu nào, điều này khiến bạn khó hiểu bất kỳ kết quả nào được trình bày ở đây, nhưng chúng tôi cũng khó chuẩn bị giải pháp hơn
  • Câu hỏi cũng thiếu "kết quả mong đợi" (kết quả mong muốn) và điều này dẫn đến việc trả lời phức tạp hơn nữa

Tôi hy vọng thông tin được cung cấp bổ sung sẽ có ích và bây giờ bạn cũng biết rằng việc trình bày dữ liệu dưới dạng nhiều hàng là điều bình thường đối với SQL. Nếu bạn không muốn hành vi bình thường đó, vui lòng nêu cụ thể về những gì bạn thực sự muốn trong câu hỏi của mình.

Tái bút. Để bao gồm một truy vấn con khác cho "những người theo dõi", bạn có thể sử dụng một truy vấn con tương tự với truy vấn mà bạn đã có. Nó có thể được thêm vào trước hoặc sau truy vấn con đó. Bạn cũng có thể thấy nó đang được sử dụng tại sqlfiddle tại đây

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

Trong khi việc thêm một truy vấn con khác có thể giải quyết mong muốn có thêm thông tin của bạn, truy vấn tổng thể có thể chậm hơn tương ứng với tốc độ phát triển dữ liệu của bạn. Một khi bạn đã giải quyết xong chức năng mà bạn thực sự cần, có thể đáng giá khi xem xét chỉ mục nào bạn cần trên các bảng đó. (Tôi tin rằng bạn nên yêu cầu lời khuyên đó một cách riêng biệt và nếu bạn chắc chắn rằng bạn bao gồm 1. DDL đầy đủ của các bảng của bạn và 2. một kế hoạch giải thích của truy vấn.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysql - Cách xử lý tìm kiếm truy vấn với các ký tự đặc biệt / (dấu gạch chéo lên) và \ (dấu gạch chéo ngược)

  2. Làm thế nào để chọn độ lệch chuẩn trong một hàng? (trong SQL - hoặc R :)

  3. Truyền không hợp lệ khi trả về mysql LAST_INSERT_ID () bằng dapper.net

  4. Cách chuyển đổi bảng kết quả thành mảng JSON trong MySQL

  5. Quyền truy cập vào vùng chứa mysql từ vùng chứa khác