用于分面搜索的SQL查询(全部输入)

用于分面搜索的SQL查询(全部输入),sql,group-by,inner-join,one-to-many,Sql,Group By,Inner Join,One To Many,好的,让我们假设一些简单的数据库。 我们有宠物表和宠物主人表,宠物的外键链接到宠物主人 pet_owner: |--id---|-----name-----| | 1 |Michael Mayers| | 2 |John Doe | | 3 |Markus Tsuker | | 4 |Bob Dilan | | 5 |Simon Pegg | pet: |--id---|----type---|--

好的,让我们假设一些简单的数据库。 我们有宠物表和宠物主人表,宠物的外键链接到宠物主人

 pet_owner:  
|--id---|-----name-----|  
|   1   |Michael Mayers|  
|   2   |John Doe      |  
|   3   |Markus Tsuker |  
|   4   |Bob Dilan     |  
|   5   |Simon Pegg    |  

 pet:
|--id---|----type---|---owner---|---name---|
|  1    |    dog    |     1     |Billy     |  
|  2    |    cat    |     1     |Willy     |
|  3    |   bird    |     1     |Dilly     |
|  4    |    dog    |     2     |Klaus     |
|  5    |    cat    |     2     |Boss      |
|  6    |    dog    |     3     |Shmat     |
|  7    |    dog    |     4     |Corin     |
|  8    |   fish    |     5     |Suzy      |
|  9    |   dog     |     1     |Mars      |
所以,简单的任务是——我需要选择同时拥有猫和狗的人。对于分面过滤来说,这是一项普通的任务

第一种方法:

SELECT
pet_owner.name
FROM pet_owner, pet
 WHERE
pet_owner.id = pet.owner AND
pet.type IN ('cat', 'dog')
GROUP BY pet_owner.name
HAVING (COUNT(DISTINCT pet.type) = 2);
第二种方法:

SELECT DISTINCT pet_owner.name
FROM pet_owner, pet T1, pet T2
WHERE pet_owner.id = T1.owner
 AND pet_owner.id = T2.owner
 AND T1.type = 'cat'
 AND T2.type = 'dog';
问题:

对于这个任务,我想还有更好的SQL查询吗? 如果没有,哪个更快?对于10个、100个、1000个独特的过滤器? 请勿在FROM子句中使用逗号;始终使用正确的显式联接语法。这是一条建议,因此您的代码看起来像是在21世纪编写的,与实际问题无关

对于这样一个问题,通常的答案是,在你的数据上尝试一下,看看哪个更快

但是,对于您的特定问题,聚合方法更好

让我承认一种偏见。无论如何,我更喜欢聚合方法。只需对查询进行简单的修改,即可更改条件,例如需要三只宠物,或检查是否有鸟类和狗。甚至猫和狗,但不是鸟

在这种情况下更好的原因是select distinct。这本质上就是在连接之上进行聚合。更糟糕的是,人们可能有多个宠物,因此连接生成的行数可能大于原始行数

事实上,有些人可能有一个小狗工厂,里面有几只宠物猫,而使用连接确实会降低查询的性能。puppy工厂对聚合查询的性能影响最小

如果您的数据一开始是不同的人,只允许使用一种类型的宠物,并且您正在寻找两种特定的宠物,那么连接查询通常会有更好的性能—它仍然取决于数据和数据库优化器中的其他因素。即使如此,出于上述原因,我仍然默认使用这些类型查询的聚合方法


我还要指出,在我的生活中,我写过一些非常复杂的查询。我想我从来没有写过一篇有1000个连接的文章。如果您正在查看那么多项目,那么分组方式将是最佳选择。查询会简单得多。

显式连接比隐式、逗号分隔的连接好。您也可以通过几种方式使用exists。我认为第一种方法会更快。您使用的是哪种产品?博士后?神谕SQL只是一种查询语言,而不是特定数据库产品的名称。@horse\u与\u no\u名称无关,真的,这并不重要。我不认为这个问题取决于平台,并没有特定的方言。好吧,我明白了。我将尝试为压力测试填充更多真实数据。例如,在Django中,第二种方法更容易实现嵌套filter@KirillShatalaev当解决特定问题时,这个答案仍然对实现/优化做出了假设,如果没有这些假设,就不会有更快或其他性能方面的更好。它依赖于DBMS,不由语言定义。