左连接多组表

时间:2013-02-14 19:54:26

标签: mysql left-join

我有一个答案表,列出了给定问题的可能答案。

possible_answer 
id question_id text
1  1           yes
2  1           no
3  2           red
4  2           blue
5  2           green

然后我有一个用户提供的答案表

user_answer
id user_id answer_id 
1  10      1
2  10      3
3  11      1
4  11      4
5  12      2
6  12      5

我正在尝试创建一个MySQL查询,它将显示用户名,用户对问题1的回答(可能为null)和用户对问题2的回答(可能为null)。我陷入困境,因为我觉得我需要将多个LEFT JOINS组合在一起,但是我得到的输出给了我一个答案,或两个列中的相同答案。

这就是我现在所拥有的:

SELECT u.name, pa1.text, pa2.text
FROM user u
LEFT JOIN user_answer ua1 ON u.id = ua1.user_id 
LEFT JOIN possible_answer pa1 ON ua1.answer_id = pa1.id AND pa1.question_id = 1
LEFT JOIN user_answer ua2 ON u.id = ua2.user_id 
LEFT JOIN possible_answer pa2 ON ua2.answer_id = pa2.id AND pa2.question_id = 2
GROUP BY u.id;

我得到的结果如下:

username  pa1.text  pa2.text
user1     yes       NULL
user2     no        NULL
user3     NULL      blue

当我知道给定用户的两个问题都有条目时。

我有group by,因为当我没有group by时,我得到了这样的结果(这更接近于预期的结果)但是它们似乎没有显示任何类型的图案:

username  pa1.text  pa2.text
    user1     yes       NULL
    user1     NULL      red
    user2     no        NULL
    user2     NULL      NULL
    user3     no        NULL
    user3     NULL      blue

任何想法都会非常感激。

5 个答案:

答案 0 :(得分:0)

也许这更接近你的追求......

Select UA.User_ID, PA.Question_ID, UA.Answer_ID, PA.Text
FROM Possible_Answer PA
LEFT JOIN user_Answer UA on PA.ID = UA.Answer_ID
ORDER BY PA.Question_ID, UA.User_ID

返回所有可能的答案,任何用户提供给问题的答案以及文本。但它会为每个用户重复问题/答案。

答案 1 :(得分:0)

如果只有两种可能性,你可以使用这个技巧:

select ua.user_id,
       min(pa.text) as answer1,
       (case when min(pa.text) <> max(pa.text) then max(pa.text) end) as answer2
from possible_answer pa join
     user_answer ua
     on pa.id = ua.answer_id
group by ua.user_id

这会丢失基于user_answer中的ID的排序。如果排序很重要,请执行min(id)max(id)并加入possible_answer以获取正确的值。

答案 2 :(得分:0)

我知道这更像是一个黑客,但也许这可以在动态查询中使用:

select z.username, w.text as PA1, x.text as PA2
from user z 
join
    (select a.user_id, b.question_id, b.text, a.answer_id
    from
    user_answer a join possible_answer b on a.answer_id=b.id) as w
    on w.user_id=z.user_id 
    and w.question_id=1

join
    (select a.user_id, b.question_id, b.text, a.answer_id
    from
    user_answer a join possible_answer b on a.answer_id=b.id) as x
    on x.user_id=z.user_id 
    and x.question_id=2

答案 3 :(得分:0)

我正在使用SQL Server,因此使用SQL Server的语法进行查询。但我相信同样的查询也可以在MySQL中运行(可能会有一些变化)。

为了获得您想要的结果,您需要将行数据转换为列。 在SQL Server中,您可以使用CASE语句(Oracle DECODE,MySQL不确定,但也可以使用CASE)

查询

SELECT u.Name, 
MAX(CASE WHEN pa1.QuestionID=1 THEN pa1.Text ELSE NULL END) AS Question1_answer,
MAX(CASE WHEN pa1.QuestionID=2 THEN pa1.Text ELSE NULL END) AS Question2_answer
FROM Users u
LEFT JOIN UserAnswers ua1 ON ua1.UserID=u.ID
LEFT JOIN PossibleAnswers pa1 ON pa1.ID=ua1.AnswerID
GROUP BY u.Name

GROUPING By Name因为我们想要一行中的问题, 所以通过名称分组并添加

MAX(...) 

到答案的列我们将一个用户的答案分组在一行

这里有一个指向SqlFiddler的链接,我尝试创建相同的情况 http://sqlfiddle.com/#!3/b2357/10

答案 4 :(得分:0)

这是最终工作的结果。

SELECT DISTINCT u.name,

(SELECT pa1.text FROM possible_answer pa1, user_answer ua WHERE ua1.user_id = u.id AND ua1.answer_id = pa1.id AND pa1.question_id = 1 ORDER BY ua1.id DESC LIMIT 1) as 'Question1',

(SELECT pa2.text FROM possible_answer aa2, user_answer ua2 WHERE ua2.user_id = u.id AND ua2.answer_id = pa2.id AND pa.question_id = 2 ORDER BY ua.id DESC LIMIT 1) as 'Question2'

FROM user u  
GROUP BY u.id;