2017-05-20 42 views
0

所以兩個具體條目一個表中選擇所有條目,我有這樣的定義2個表:從具有另一個表

CREATE TABLE tblPersons (
    id INTEGER PRIMARY KEY AUTOINCREMENT, 
    name TEXT 
); 

CREATE TABLE tblHobbies (
    person_id INTEGER REFERENCES tblPersons (id), 
    hobby  TEXT 
); 

再舉例來說,我已經加入到tblPersons 3人:

1 | skiing 
1 | serfing 
1 | hiking 
1 | gunsmithing 
1 | driving 
2 | table tennis 
2 | driving 
2 | hiking 
3 | reading 
3 | scuba diving 
:在 tblHobbies
1 | John 
2 | Bob 
3 | Eve 

而旁邊的愛好

而我需要的是查詢,它會給我一個有幾個特定愛好的人的名單。

我能想出的唯一的事情,是這樣的:

SELECT id, name FROM tblPersons 
    INNER JOIN tblHobbies as hobby1 ON hobby1.hobby = 'driving' 
    INNER JOIN tblHobbies as hobby2 ON hobby2.hobby = 'hiking' 
    WHERE tblPersons.id = hobby1.person_id and tblPersons.id = hobby2.person_id; 

但它是相當緩慢。沒有更好的解決方案嗎?

+0

這將是更好的方式有三個表:人,霍s和person_hobbies。所以你會在愛好桌上擁有一次興趣愛好,並且可以省去拼寫錯誤(例如鋸齒/衝浪)。 –

回答

1

首先,您沒有tblHobbies上的主鍵,這是查詢速度慢(以及其他問題)的一個原因。你也應該考慮在tblHobbies.hobby上創建一個索引。第二,我會建議你創建第三張表來證明存在於你的模型中的N:N基數,並避免多餘的業餘愛好。例如:

--Person 
CREATE TABLE tblPersons (
    id INTEGER PRIMARY KEY AUTOINCREMENT, 
    name TEXT 
); 

--Hobby 
CREATE TABLE tblHobbies (
    id INTEGER PRIMARY KEY AUTOINCREMENT, 
    hobby TEXT 
); 

--Associative table between Person and Hobby 
CREATE TABLE tblPersonsHobbies (
    person_id INTEGER REFERENCES tblPersons (id), 
    hobby_id INTEGER REFERENCES tblHobbies (id), 
    PRIMARY KEY (person_id, hobby_id) 
); 

添加一個額外的表,但它是值得的。

--Query on your current model 
SELECT id, name FROM tblPersons 
    INNER JOIN tblHobbies as hobby1 ON tblPersons.id = hobby1.person_id 
    WHERE hobby1.hobby IN ('driving', 'hiking'); 

--Query on suggested model 
SELECT id, name FROM tblPersons 
    INNER JOIN tblPersonsHobbies as personsHobby ON tblPersons.id = personsHobby.person_id 
    INNER JOIN tblHobbies as hobby1 ON hobby1.id = personsHobby.hobby_id 
     WHERE hobby1.hobby IN ('driving', 'hiking'); 
+0

不幸的是,對建議模塊的查詢並不適合我,因爲它向我展示了一個擁有興趣愛好的人。 – externum

+0

@externum啊,好的。我錯過了這部分。我會編輯我的答案。 –

+0

另外創建索引真的有幫助。 – externum

1

可以聚集愛好表獲得人與兩個愛好:

select person_id 
from tblhobbies 
group by person_id 
having count(case when hobby = 'driving' then 1 end) > 0 
    and count(case when hobby = 'hiking' then 1 end) > 0 

或者用WHERE子句限制記錄更好的閱讀:

select person_id 
from tblhobbies 
where hobby in ('driving', 'hiking') 
group by person_id 
having count(distinct hobby) =2 

(應該有然而,你可以刪除DISTINCT,正如我在評論部分所說,它甚至應該是person_id + hob帶獨立愛好表的by_id。編輯:哎呀,我應該讀其他答案。米哈爾建議這個數據模型三小時前已經:-)

如果你想要的名字,在那裏你會發現在上面的查詢的ID人員表中選擇:

select id, name 
from tblpersons 
where id in 
(
    select person_id 
    from tblhobbies 
    where hobby in ('driving', 'hiking') 
    group by person_id 
    having count(distinct hobby) =2 
); 

有了更好的數據模型,你」 d放回

from tblhobbies 
    where hobby in ('driving', 'hiking') 
    group by person_id 
    having count(distinct hobby) =2 

from tblpersonhobbies 
    where hobby_id in (select id from tblhobbies where hobby in ('driving', 'hiking')) 
    group by person_id 
    having count(*) =2 
+0

第一個查詢實際上比較慢( – externum