使用 SQL 过滤
Filtering with SQL
我正在尝试编写一个 SQL 查询来过滤数据集中的人员。
有一些"facets",比如"How old is the person?","How tall is the person?"。
每个方面都有一些 "buckets"。例如,"How old?" 方面可能有桶“0-20”、“21-40”、“40+”。
有一些 "memberships",这是一个连接 table 来声明一个人属于特定的桶。
我的模型是这样的:
Facet
|
/|\
Bucket
|
/|\
Membership
\|/
|
Person
我遇到困难的部分是,为了能够进行过滤,我需要在各个方面进行交集。
例如,我希望能够为 "How old?" 选择“0-20”和“21-40”,为 "How tall?" 选择“0-140”。返回的人应该是:
(桶“0-20”中的人或桶“21-40”中的人)和桶“0-140”中的人
我不太确定该怎么做。我可以使用 "IN" 子句轻松完成 "OR",例如IN (1, 2, 3),但我不确定 "AND"。我看到 SQL 有一个 "INTERSECT" 关键字,但我不确定这是否是正确的方法。
非常感谢任何帮助。
谢谢
编辑:这是(简化的)架构:
方面:id
桶:id,facet_id
成员资格:person_id、bucket_id
人:id
所有字段都是整数。
编辑:这是我迄今为止最好的查询。
select group_concat(p.id) as "people for facet",
b.facet_id from people p
join memberships m on m.person_id = p.id
join buckets b on m.bucket_id = b.id
where b.id in (1, 3)
group by b.facet_id;
我现在需要将 "people for facet" 结果相交。
假设任何给定的桶只是单个方面的一部分,那么有一个非常优雅的解决方案。挑战在于以正确的方式看待问题。所以,如果您想要匹配您所有方面的用户,
select b.userid
from buckets b
where b.bucketid in ( . . . )
group by b.userid
having count(distinct b.facetid) = # of facets;
我们的想法是您有一个存储桶列表并表示您想要的方面。您希望确保每个 "facet" 至少有一个匹配的存储桶,这就是 having
子句的作用。
谢谢戈登。我终于明白了!您对问题的颠倒思考方式有所帮助。
这是我的解决方案:
select p.* from memberships m
join people p on m.person_id = p.id
join buckets b on m.bucket_id = b.id
where b.id in (1, 3)
group by m.person_id
having count(distinct b.facet_id) = (
select count(distinct b.facet_id) from buckets b
where b.id in (1, 3)
);
输入是桶列表 (1, 3)。
我使用子查询来计算这些桶的分面数。也许有更高效的方法,但我认为无论如何都会很快执行。
我将在大型数据集上对此进行测试,看看它的表现如何。
再次感谢。
我正在尝试编写一个 SQL 查询来过滤数据集中的人员。
有一些"facets",比如"How old is the person?","How tall is the person?"。
每个方面都有一些 "buckets"。例如,"How old?" 方面可能有桶“0-20”、“21-40”、“40+”。
有一些 "memberships",这是一个连接 table 来声明一个人属于特定的桶。
我的模型是这样的:
Facet
|
/|\
Bucket
|
/|\
Membership
\|/
|
Person
我遇到困难的部分是,为了能够进行过滤,我需要在各个方面进行交集。
例如,我希望能够为 "How old?" 选择“0-20”和“21-40”,为 "How tall?" 选择“0-140”。返回的人应该是:
(桶“0-20”中的人或桶“21-40”中的人)和桶“0-140”中的人
我不太确定该怎么做。我可以使用 "IN" 子句轻松完成 "OR",例如IN (1, 2, 3),但我不确定 "AND"。我看到 SQL 有一个 "INTERSECT" 关键字,但我不确定这是否是正确的方法。
非常感谢任何帮助。
谢谢
编辑:这是(简化的)架构:
方面:id
桶:id,facet_id
成员资格:person_id、bucket_id
人:id
所有字段都是整数。
编辑:这是我迄今为止最好的查询。
select group_concat(p.id) as "people for facet",
b.facet_id from people p
join memberships m on m.person_id = p.id
join buckets b on m.bucket_id = b.id
where b.id in (1, 3)
group by b.facet_id;
我现在需要将 "people for facet" 结果相交。
假设任何给定的桶只是单个方面的一部分,那么有一个非常优雅的解决方案。挑战在于以正确的方式看待问题。所以,如果您想要匹配您所有方面的用户,
select b.userid
from buckets b
where b.bucketid in ( . . . )
group by b.userid
having count(distinct b.facetid) = # of facets;
我们的想法是您有一个存储桶列表并表示您想要的方面。您希望确保每个 "facet" 至少有一个匹配的存储桶,这就是 having
子句的作用。
谢谢戈登。我终于明白了!您对问题的颠倒思考方式有所帮助。
这是我的解决方案:
select p.* from memberships m
join people p on m.person_id = p.id
join buckets b on m.bucket_id = b.id
where b.id in (1, 3)
group by m.person_id
having count(distinct b.facet_id) = (
select count(distinct b.facet_id) from buckets b
where b.id in (1, 3)
);
输入是桶列表 (1, 3)。
我使用子查询来计算这些桶的分面数。也许有更高效的方法,但我认为无论如何都会很快执行。
我将在大型数据集上对此进行测试,看看它的表现如何。
再次感谢。