MySQL Left Join с условным

0

Кажется довольно простым, у меня есть "вопрос в таблице", в котором хранится список всех вопросов и множество таблиц, которые находятся между "вопросом" и "пользователем" под названием "question_answer".

Можно ли сделать один запрос, чтобы вернуть все вопросы в таблицу вопросов и те ответы, на которые пользователь ответил без ответа на вопросы, имеющие значения NULL.

Вопрос:

| 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
Теги:

4 ответа

1

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

  • 0
    да, это работает, только если у каждого вопроса есть строка в таблице question_answer.
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
    я извиняюсь, но я не могу поверить, что вы приняли этот ответ paste.pocoo.org/show/254375
  • 0
    Я удалил GROUP BY как он не нужен (он был только там, как это было в исходном запросе). И добавил порядок по пункту. Чтобы получить вопросы для более чем одного пользователя, вы можете просто изменить условие объединения, чтобы использовать user_id IN (...) .
Показать ещё 1 комментарий
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;

edit: добавлена ​​статистика/пояснения и время выполнения:

время выполнения: 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 довольно тривиален.
Показать ещё 3 комментария
0

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню