簡體   English   中英

從一個表中選擇所有條目,在另一個表中有兩個特定條目

[英]Select all entries from one table which has two specific entries in another table

因此,我有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 | John
2 | Bob
3 | Eve

還有tblHobbies中的下一個愛好:

1 | skiing
1 | serfing
1 | hiking
1 | gunsmithing
1 | driving
2 | table tennis
2 | driving
2 | hiking
3 | reading
3 | scuba diving

我需要的是查詢,該查詢將向我返回具有一些特定愛好的人的列表。

我唯一能想到的是:

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;

但這很慢。 有沒有更好的解決方案?

首先,您在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');

您可以匯總興趣愛好表以同時獲得兩個興趣愛好的人:

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

(不過,表中的person + hobby應該有一個唯一的約束。然后,您可以刪除DISTINCT 。正如我在評論部分中所說的,它甚至應該是person_id + hobby_id,並帶有一個單獨的hobby表。編輯:糟糕,我本應該閱讀其他答案的。Michal已經在三個小時前提出了這個數據模型:-)

如果需要名稱,請從人員表中選擇,在上面的查詢中找到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
);

使用更好的數據模型,您將取代

  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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM