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

Menulis Query MySQL yang Kompleks

Saya akan tergoda untuk memiliki sub kueri yang mendapatkan semua kata yang telah dipelajari seseorang dan menggabungkannya dengan dirinya sendiri, dengan kata-kata GROUP_CONCAT bersama dengan hitungan. Jadi memberi:-

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

Jadi sub kuerinya akan seperti:-

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

memberikan

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

Kemudian gabungkan hasilnya dengan tabel lainnya, periksa artikel yang idword utamanya cocok tetapi tidak ada id lainnya yang ditemukan.

Sesuatu seperti ini (walaupun tidak diuji karena tidak ada data uji):-

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 

EDIT - diperbarui untuk mengecualikan artikel dengan lebih dari 10 kata yang belum dipelajari.

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

EDIT - coba mengomentari kueri di atas:-

Ini hanya memilih kolom

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

Sub kueri ini mendapatkan setiap kata yang dipelajari, bersama dengan daftar kata yang dipisahkan koma dengan order_learned yang lebih besar. Ini untuk id pengguna tertentu

(
    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 

Ini hanya untuk mendapatkan artikel kata-kata (yaitu, kata-kata yang dipelajari dari sub query di atas) digunakan di

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

Sub query ini mendapatkan artikel yang memiliki kurang dari 10 kata di dalamnya yang belum dipelajari oleh pengguna tertentu.

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

Gabung ini untuk menemukan artikel yang memiliki kata-kata dalam daftar yang dipisahkan koma dari sub kueri pertama (yaitu kata-kata dengan order_learned yang lebih besar). Ini dilakukan sebagai LEFT OUTER JOIN karena saya ingin mengecualikan kata apa pun yang ditemukan (ini dilakukan di klausa WHERE dengan memeriksa 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. LOAD DATA LOCAL INFILE tidak berfungsi dari php 5.5 menggunakan PDO

  2. Cetak hasil dalam format MySQL dengan Python

  3. Mengapa baris cocok tetapi tidak diubah dengan pernyataan pembaruan mysql?

  4. Ubah nomor awal kenaikan otomatis?

  5. Alat terbaik untuk menyinkronkan database MySQL