Mysql
 sql >> база данни >  >> RDS >> Mysql

Писане на сложна MySQL заявка

Бих се изкушил да имам подзаявка, която получава всички думи, които човек е научил, и да се присъединя към нея срещу себе си, с думите GROUP_CONCAT заедно с преброяване. Така че давам:-

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

Така че подзаявката ще бъде нещо като:-

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

даване

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

След това съединете резултатите от това с другите таблици, като проверите за статии, в които основните идентификационни думи съвпадат, но нито една от другите не е намерена.

Нещо подобно (въпреки че не е тествано, тъй като няма тестови данни):-

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 

РЕДАКТИРАНЕ – актуализирано, за да изключи статии с повече от 10 думи, които все още не са научени.

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

РЕДАКТИРАНЕ - опит за коментиране на горната заявка:-

Това само избира колоните

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

Тази подзаявка получава всяка от научените думи, заедно с разделен със запетая списък на думите с по-голям order_learned. Това е за конкретен потребителски идентификатор

(
    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

Тази подзаявка получава статиите, които имат по-малко от 10 думи, които все още не са научени от конкретния потребител.

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

Това обединяване е за намиране на статии, които имат думи в списъка, разделени със запетая, от първата подзаявка (т.е. думи с по-голям order_learned). Това се прави като LEFT OUTER JOIN, тъй като искам да изключа всички намерени думи (това се прави в клаузата WHERE чрез проверка за 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. MySQL - Как да увеличите размера на varchar на съществуваща колона в база данни, без да нарушавате съществуващите данни?

  2. Как да форматирате числа в MySQL

  3. FIND_IN_SET() срещу IN()

  4. Курсор на MySQL съхранена процедура за подготвени оператори

  5. Резултати от текстовото поле за автоматично довършване на базата на SQL база данни