2010-11-17 82 views
1

我正在尝试做一个相当复杂的(对于我来说,至少)查询,涉及获取可能具有NULL值的行。MySQL与NULL值联接

这里有四个表,tags,questions_tags,users_experienceanswers。连接相当简单。问题被标记,标签有名称,用户给出问题的答案,用户有特定标签的经验。我想找到用户提供的答案,以及他们的经验(可能为NULL)。我按照特定标签给出的答案数排序。

我的查询如下。这是不是在所有优化(如果你有优化建议,请建议走!):

SELECT t.tag_id, t.name, ue.body, COUNT(a.qid) 
FROM tags AS t 
LEFT JOIN users_experience AS ue 
    ON t.tag_id = ue.tag_id 
LEFT JOIN questions_tags AS qt 
    ON qt.tag_id = t.tag_id 
LEFT JOIN answers AS a 
    ON a.qid = qt.qid 
WHERE a.uid=1 
GROUP BY t.tag_id 
ORDER BY COUNT(a.qid) DESC; 

我面对上述查询的问题是,如果有人已经指出特定标签的经验,这将显示给用户是否是他们的经验。我想只看到特定用户的体验,这个查询只是没有做到。我在其他地方遇到过这个问题并被困住了,所以不得不绕过它。

我试着在查询中添加AND ue.uid = 1,但这样会限制只有已经给出经验的人的结果,并且不会返回我期望的NULL值。

想怎么做?

回答

2

您的AND ue.uid = 1本能没有错,但它属于ON条款,因此它是JOIN的一部分,它用于确定哪些行有资格加入。

LEFT JOIN users_experience AS ue 
    ON t.tag_id = ue.tag_id AND ue.uid = a.uid 

(这应该一起再下answers放在一起。)

+0

真棒,谢谢! – 2010-11-17 22:41:30

0

我认为你需要包括一个用户的表。通过用户表中的uid进行过滤(它保证在哪里),并且应该给你想要的。 (包括空值)。我不知道你的用户表看起来完全像什么,但我假设你的查询将是这样的:

SELECT t.tag_id, t.name, ue.body, COUNT(a.qid) 
    FROM users 
LEFT JOIN users_experience AS ue 
    ON users.uid = ue.uid 
LEFT JOIN tags 
    ON t.tag_id = ue.tag_id 
LEFT JOIN questions_tags AS qt 
    ON qt.tag_id = t.tag_id 
LEFT JOIN answers AS a 
    ON a.qid = qt.qid 
WHERE users.uid=1 
GROUP BY t.tag_id 
ORDER BY COUNT(a.qid) DESC; 

至于优化 - LEFT JOIN通常被认为是不好,除非这些表是非常小的。 MySQL基本上必须搜索整个表的值为NULL。实际上,检查用户是否先在左侧连接表中有记录,并且仅在发现记录时才使用常规JOIN发出第二个查询可能会更快。

希望有帮助!

+0

你不再加入到'上的相关标签users_experience';你正在计算所有领域的所有经验。如果“uid”值已经可用,则不需要加入“用户”(这样做只会增加不必要的处理)。 – VoteyDisciple 2010-11-17 22:37:11

+0

@VoteyDisciple - 他想要用户的信息,他们有经验与否。他原来的问题表明,当他添加一个用户ID时,他没有得到NULL值。这是因为user_experience表中的用户标识为空。我反过来在users_experience上加入了标签。它仍然有效。 (注意我不认为这是个好主意,我认为他应该重新考虑他的桌子设计) – Cfreak 2010-11-18 15:05:12