2010-08-25 143 views
0

這似乎很簡單,我有一個表'問題',它存儲了所有問題的列表以及位於'問題'和'用戶'之間的多對多表,稱爲'question_answer'。MySQL左有條件加入

是否有可能做一個查詢回去問表內和所有問題的那些用戶已與聯合國回答回答問題是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 

回答

0

不應該使用RIGHT JOIN?

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 2010-08-25 10:53:09

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個問題,350萬個答案)

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

這裏不需要交叉連接,即使是適度的數據集也會很昂貴。 – 2010-08-25 12:27:05

+0

我懷疑這將是昂貴的考慮到他們正在指定一個用戶。 1個用戶* n個問題* n ans是一件小事。 – 2010-08-25 12:36:22

+0

我的道歉,在這裏它實際上是一個內部連接,因爲連接條件在問題表上包含一個謂詞。 – 2010-08-25 17:10:25

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

我是sry,但我不能相信你已經對這個答案進行了解釋http://paste.pocoo.org/show/254375/ – 2010-08-25 17:16:22

+0

我刪除了'GROUP BY',因爲它是不必要的(它只是在那裏因爲它在原始查詢中)。並添加了按條款的順序。 要獲得多個用戶的問題,只需更改連接條件以使用'user_id IN(...)'。 – 2010-08-26 19:51:27

+0

@ar - 它仍然無法正常工作,請看看以下內容:http://i37.tinypic.com/24y8w2s.jpg – 2010-08-26 23:17:33