注意:您可以在此处找到上一个问题及其答案。对它的深入测试证明了之前的答案是错误的:Writing a Complex MySQL Query
我有3张桌子。
表Words_Learned
包含用户已知的所有单词,以及单词学习的顺序。它有3列1)单词ID和2)用户ID和3)学习单词的顺序。
表Article
包含文章。它有3列1)文章ID,2)唯一字数和3)文章内容。
表Words
包含每篇文章中包含的所有唯一单词的列表。它有2列1)字ID和2)文章ID
数据库图如下/
现在,使用此数据库并仅使用"" mysql,我需要做以下工作。
给定一个用户ID,它应该得到该用户已知的所有单词的列表,按照学习它们的顺序排序。换句话说,最近学过的单词将位于列表的顶部。
假设对用户ID的查询显示他们已经记住了以下3个单词,并且我们跟踪他们学习单词的顺序。 八达通 - 3 狗 - 2 勺子 - 1
首先,我们获得包含Octopus一词的所有文章的列表,然后使用表Words
对这些文章进行计算。计算意味着如果该文章包含超过10个未出现在用户词汇表列表中的单词(从表words_learned
中提取),则它将从列表中排除。
然后,我们查询包含dog的所有记录,但不要包含“章鱼”
然后,我们查询包含勺子的所有记录,但不要包含八达通或狗的字样
在我们找到符合此条件的100条记录之前,您一直在执行此重复过程。
为了实现这个过程,我做了以下(请访问SQLFiddle链接以查看表结构,测试数据和我的查询)
http://sqlfiddle.com/#!2/48dae/1
在我的查询中,您可以看到生成的结果,但它们无效。但是在"正确的查询",结果应该是,
Level 1
Level 1
Level 1
Level 2
Level 2
Level 2
Level 3
Level 3
这是一个更好理解的博士。
Do while articles found < 100
{
for each ($X as known words, in order that those words were learned)
{
Select all articles that contain the word $X, where the 1) article has not been included in any previous loops, and 2)where the count of "unknown" words is less than 10.
Keep these articles in order.
}
}
答案 0 :(得分:1)
select * from (
select a.idArticle, a.content, max(`order`) max_order
from words_learned wl
join words w on w.idwords = wl.idwords
join article a on a.idArticle = w.idArticle
where wl.userId = 4
group by a.idArticle
) a
left join (
select count(*) unknown_count, w2.idArticle from words w2
left join words_learned wl2 on wl2.idwords = w2.idwords
and wl2.userId = 4
where wl2.idwords is null
group by w2.idArticle
) unknown_counts on unknown_counts.idArticle = a.idArticle
where unknown_count is null or unknown_count < 10
order by max_order desc
limit 100
http://sqlfiddle.com/#!2/6944b/9
第一个派生表选择给定用户知道一个或多个单词的唯一文章以及这些单词的最大order
值。最大订单值用于对最终结果进行排序,以便首先显示包含高阶词的文章。
第二个派生表计算给定用户对每篇文章不知道的单词数。此表用于排除任何包含10个或更多用户不知道的单词的文章。