[英]Select all entries from one table which has two specific entries in another table
So, I have 2 tables defined like this: 因此,我有2个这样定义的表:
CREATE TABLE tblPersons (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT
);
CREATE TABLE tblHobbies (
person_id INTEGER REFERENCES tblPersons (id),
hobby TEXT
);
And for example I have 3 person added to tblPersons : 例如,我在tblPersons中添加了3个人:
1 | John
2 | Bob
3 | Eve
And next hobbies in tblHobbies : 还有tblHobbies中的下一个爱好:
1 | skiing
1 | serfing
1 | hiking
1 | gunsmithing
1 | driving
2 | table tennis
2 | driving
2 | hiking
3 | reading
3 | scuba diving
And what I need, is query which will return me a list of person who have several specific hobbies. 我需要的是查询,该查询将向我返回具有一些特定爱好的人的列表。
The only thing I could've come up with, is this: 我唯一能想到的是:
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;
But it is rather slow. 但这很慢。 Isn't there any better solution?
有没有更好的解决方案?
First, you don't have a Primary Key on tblHobbies
this is one cause of slow query (and other problems). 首先,您在
tblHobbies
上没有主键,这是查询缓慢(以及其他问题)的原因之一。 Also you should consider creating a index on tblHobbies.hobby
. 另外,您应该考虑在
tblHobbies.hobby
上创建索引。
Second, I'd to advice you to create a third table to evidence N:N cardinality that exists in your model and avoid redundant hobbies. 其次,我建议您创建第三个表以证明模型中存在N:N基数,并避免多余的爱好。 Something like:
就像是:
--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)
);
Adds an extra table but it's worth it. 添加一个额外的表,但这是值得的。
--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');
You can aggregate the hobbies table to get persons with both hobbies: 您可以汇总兴趣爱好表以同时获得两个兴趣爱好的人:
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
Or better with a WHERE
clause restricting the records to read: 最好使用
WHERE
子句来限制记录的读取:
select person_id
from tblhobbies
where hobby in ('driving', 'hiking')
group by person_id
having count(distinct hobby) =2
(There should be a unique constraint on person + hobby in the table, though. Then you could remove the DISTINCT
. And as I said in the comments section it should even be person_id + hobby_id with a separate hobbies table. EDIT: Oops, I should have read the other answer. Michal suggested this data model three hours ago already :-) (不过,表中的person + hobby应该有一个唯一的约束。然后,您可以删除
DISTINCT
。正如我在评论部分中所说的,它甚至应该是person_id + hobby_id,并带有一个单独的hobby表。编辑:糟糕,我本应该阅读其他答案的。Michal已经在三个小时前提出了这个数据模型:-)
If you want the names, select from the persons table where you find the IDs in above query: 如果需要名称,请从人员表中选择,在上面的查询中找到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
);
With the better data model you'd replace 使用更好的数据模型,您将取代
from tblhobbies
where hobby in ('driving', 'hiking')
group by person_id
having count(distinct hobby) =2
with 与
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.