2010-08-25 2 views
0

Кажется довольно простым, у меня есть стол «вопрос», в котором хранится список всех вопросов и много-много таблиц, которые находятся между «вопросом» и «пользователем» под названием «question_answer».MySQL Left Join with conditional

Можно сделать один запрос, чтобы получить обратно все вопросы в таблице вопросов и те, пользователь ответил с ООН ответила на вопросы быть нулевыми значениями

вопрос:

| id | question | 

question_answer:

| id | question_id | answer | user_id | 

Я делаю этот запрос, но условие обеспечивает, чтобы возвращались только ответы на вопросы. Нужно ли мне прибегать к вложенному выбору?

SELECT * FROM `question` LEFT JOIN `question_answer` 
ON question_answer.question_id = question.id 
WHERE user_id = 14583461 GROUP BY question_id 

ответ

0

Не следует ли использовать ПРАВИЛЬНОЕ СОЕДИНЕНИЕ?

SELECT * FROM question_answer RIGHT JOIN question ON question_answer.question_id = question.id 
WHERE user_id = 14583461 GROUP BY question_id 
1

если user_id находится во внешнем присоединился к столу, то ваш предикат user_id = 14583461 приведет не возвращает ни одной строки, где user_id равно нулю, т.е. строк с неотвеченных вопросов. Вы должны сказать "user_id = 14583461 или user_id является нулевым"

+0

Да, это работает только в том случае, если каждый вопрос имеет строку в таблице question_answer. – bertsisterwanda

0

что-то подобное может помочь (http://pastie.org/1114844)

drop table if exists users; 
create table users 
(
user_id int unsigned not null auto_increment primary key, 
username varchar(32) not null 
)engine=innodb; 

drop table if exists question; 
create table question 
(
question_id int unsigned not null auto_increment primary key, 
ques varchar(255) not null 
)engine=innodb; 

drop table if exists question_ans; 
create table question_ans 
(
user_id int unsigned not null, 
question_id int unsigned not null, 
ans varchar(255) not null, 
primary key (user_id, question_id) 
)engine=innodb; 

insert into users (username) values 
('user1'),('user2'),('user3'),('user4'); 

insert into question (ques) values 
('question1 ?'),('question2 ?'),('question3 ?'); 

insert into question_ans (user_id,question_id,ans) values 
(1,1,'foo'), (1,2,'mysql'), (1,3,'php'), 
(2,1,'bar'), (2,2,'oracle'), 
(3,1,'foobar'); 

select 
u.*, 
q.*, 
a.ans 
from users u 
cross join question q 
left outer join question_ans a on a.user_id = u.user_id and a.question_id = q.question_id 
order by 
u.user_id, 
q.question_id; 

select 
u.*, 
q.*, 
a.ans 
from users u 
cross join question q 
left outer join question_ans a on a.user_id = u.user_id and a.question_id = q.question_id 
where 
u.user_id = 2 
order by 
q.question_id; 

изменения: добавлены некоторые статистические данные/объяснить план & выполнения:

выполнения: 0,031 (10 000 пользователей, 1000 вопросов, 3,5 миллиона ответов)

select count(*) from users 
count(*) 
======== 
10000 

select count(*) from question 
count(*) 
======== 
1000 

select count(*) from question_ans 
count(*) 
======== 
3682482 

explain 
select 
u.*, 
q.*, 
a.ans 
from users u 
cross join question q 
left outer join question_ans a on a.user_id = u.user_id and a.question_id = q.question_id 
where 
u.user_id = 256 
order by 
u.user_id, 
q.question_id; 


id select_type table type possible_keys key   key_len ref       rows Extra 
== =========== ===== ==== ============= ===   ======= ===       ==== ===== 
1 SIMPLE   u const PRIMARY   PRIMARY   4 const      1  Using filesort 
1 SIMPLE   q ALL                  687 
1 SIMPLE   a eq_ref PRIMARY   PRIMARY   8 const,foo_db.q.question_id 1 
+0

Крестовое соединение здесь не требуется и будет стоить дорого даже на скромных наборах данных. –

+0

Я сомневаюсь, что это будет дорого, учитывая, что они указывают одного пользователя. 1 пользователь * n вопросов * n ans довольно тривиален. –

+0

Приносим извинения, здесь это действительно внутреннее соединение, так как условие соединения включает предикат в таблице вопросов. –

0

Переместить предикат user_id в состояние соединения. Это гарантирует, что будут возвращены все строки из question, но только строки из question_answer с указанным идентификатором пользователя и идентификатором вопроса.

SELECT * FROM question 
    LEFT JOIN question_answer ON question_answer.question_id = question.id 
           AND user_id = 14583461 
ORDER BY user_id, question_id 
+0

Я плачу, но я не могу поверить, что вы воспользовались этим ответом. Http://paste.pocoo.org/show/254375/ –

+0

Я удаляю 'GROUP BY', поскольку это не нужно (это было только там как это было в исходном запросе). И добавил заказ по статье. Чтобы задать вопросы для нескольких пользователей, вы можете просто изменить условие соединения, чтобы использовать 'user_id IN (...)'. –

+0

@ar - он все еще не работает должным образом, пожалуйста, взгляните на следующее: http://i37.tinypic.com/24y8w2s.jpg –