从一个表中选择所有条目,该表在另一个表中具有两个特定条目

时间:2017-05-20 15:43:33

标签: sql database sqlite

所以,我有两个像这样定义的表:

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

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

例如,我有3个人加入 tblPersons

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;

但它很慢。没有更好的解决方案吗?

2 个答案:

答案 0 :(得分: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');

答案 1 :(得分: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 + hobby_id,并且有一个单独的爱好编辑:哎呀,我应该读另一个答案.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