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

Viết một truy vấn MySQL phức tạp

Tôi muốn có một truy vấn phụ lấy tất cả các từ mà một người đã học được và nối từ đó với chính nó, với các từ GROUP_CONCAT cùng với một số lượng. Vì vậy, cho:-

Octopus, NULL, 0
Dog, "Octopus", 1
Spoon, "Octopus,Dog", 2

Vì vậy, truy vấn phụ sẽ giống như sau:-

SELECT sub0.idwords, GROUP_CONCAT(sub1.idwords) AS excl_words, COUNT(sub1.idwords) AS older_words_cnt
FROM words_learned sub0
LEFT OUTER JOIN words_learned sub1
ON sub0.userId = sub1.userId
AND sub0.order_learned < sub1.order_learned
WHERE sub0.userId = 1
GROUP BY sub0.idwords

cho

idwords    excl_words    older_words_cnt
1          NULL          0
2          1             1
3          1,2           2

Sau đó, kết hợp các kết quả của điều này với các bảng khác, kiểm tra các bài viết trong đó các idwords chính khớp nhưng không tìm thấy các idwords khác.

Một cái gì đó như thế này (mặc dù không được kiểm tra vì không có dữ liệu kiểm tra):-

SELECT sub_words.idwords, words_inc.idArticle
(
    SELECT sub0.idwords, SUBSTRING_INDEX(GROUP_CONCAT(sub1.idwords), ',', 10) AS excl_words, COUNT(sub1.idwords) AS older_words_cnt
    FROM words_learned sub0
    LEFT OUTER JOIN words_learned sub1
    ON sub0.userId = sub1.userId
    AND sub0.order_learned < sub1.order_learned
    WHERE sub0.userId = 1
    GROUP BY sub0.idwords
) sub_words
INNER JOIN words words_inc
ON sub_words.idwords = words_inc.idwords
LEFT OUTER JOIN words words_exc
ON words_inc.idArticle = words_exc.idArticle
AND FIND_IN_SET(words_exc.idwords, sub_words.excl_words)
WHERE words_exc.idwords IS NULL
ORDER BY older_words_cnt
LIMIT 100 

CHỈNH SỬA - cập nhật để loại trừ các bài viết có hơn 10 từ chưa được học.

SELECT sub_words.idwords, words_inc.idArticle,
sub2.idArticle, sub2.count, sub2.content
FROM
(
    SELECT sub0.idwords, GROUP_CONCAT(sub1.idwords) AS excl_words, COUNT(sub1.idwords) AS older_words_cnt
    FROM words_learned sub0
    LEFT OUTER JOIN words_learned sub1
    ON sub0.userId = sub1.userId
    AND sub0.order_learned < sub1.order_learned
    WHERE sub0.userId = 1
    GROUP BY sub0.idwords
) sub_words 
INNER JOIN words words_inc
ON sub_words.idwords = words_inc.idwords
INNER JOIN
(
    SELECT a.idArticle, a.count, a.content, SUM(IF(c.idwords_learned IS NULL, 1, 0)) AS unlearned_words_count
    FROM Article a
    INNER JOIN words b
    ON a.idArticle = b.idArticle
    LEFT OUTER JOIN words_learned c
    ON b.idwords = c.idwords
    AND c.userId = 1
    GROUP BY a.idArticle, a.count, a.content
    HAVING unlearned_words_count < 10
) sub2
ON words_inc.idArticle = sub2.idArticle
LEFT OUTER JOIN words words_exc
ON words_inc.idArticle = words_exc.idArticle
AND FIND_IN_SET(words_exc.idwords, sub_words.excl_words)
WHERE words_exc.idwords IS NULL
ORDER BY older_words_cnt
LIMIT 100

CHỈNH SỬA - cố gắng nhận xét truy vấn trên:-

Thao tác này chỉ chọn các cột

SELECT sub_words.idwords, words_inc.idArticle,
sub2.idArticle, sub2.count, sub2.content
FROM

Truy vấn phụ này lấy từng từ đã học, cùng với danh sách các từ được phân tách bằng dấu phẩy có order_learned lớn hơn. Điều này dành cho một id người dùng cụ thể

(
    SELECT sub0.idwords, GROUP_CONCAT(sub1.idwords) AS excl_words, COUNT(sub1.idwords) AS older_words_cnt
    FROM words_learned sub0
    LEFT OUTER JOIN words_learned sub1
    ON sub0.userId = sub1.userId
    AND sub0.order_learned < sub1.order_learned
    WHERE sub0.userId = 1
    GROUP BY sub0.idwords
) sub_words 

Điều này chỉ để lấy các bài báo mà các từ (tức là các từ đã học được từ truy vấn phụ ở trên) được sử dụng trong

INNER JOIN words words_inc
ON sub_words.idwords = words_inc.idwords

Truy vấn phụ này nhận các bài báo có ít hơn 10 từ mà người dùng cụ thể chưa học được.

INNER JOIN
(
    SELECT a.idArticle, a.count, a.content, SUM(IF(c.idwords_learned IS NULL, 1, 0)) AS unlearned_words_count
    FROM Article a
    INNER JOIN words b
    ON a.idArticle = b.idArticle
    LEFT OUTER JOIN words_learned c
    ON b.idwords = c.idwords
    AND c.userId = 1
    GROUP BY a.idArticle, a.count, a.content
    HAVING unlearned_words_count < 10
) sub2
ON words_inc.idArticle = sub2.idArticle

Sự kết hợp này là để tìm các bài viết có các từ trong danh sách được phân tách bằng dấu phẩy từ truy vấn phụ thứ nhất (tức là các từ có thứ tự_đặt_biệt lớn hơn). Điều này được thực hiện dưới dạng THAM GIA NGOÀI TRÁI vì tôi muốn loại trừ bất kỳ từ nào được tìm thấy (điều này được thực hiện trong mệnh đề WHERE bằng cách kiểm tra NULL)

LEFT OUTER JOIN words words_exc
ON words_inc.idArticle = words_exc.idArticle
AND FIND_IN_SET(words_exc.idwords, sub_words.excl_words)
WHERE words_exc.idwords IS NULL
ORDER BY older_words_cnt
LIMIT 100


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Các trường đa ngôn ngữ trong bảng DB

  2. Cột SQLAlchemy JSON - cách thực hiện truy vấn chứa

  3. mysql:nhận số lượng bản ghi giữa hai ngày-giờ

  4. Cách chính tắc để kéo một bản ghi từ cơ sở dữ liệu MySQL có trường nhỏ nhất / lớn nhất là gì?

  5. Kiểm tra các bản sao trước khi chèn