用于分面搜索的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,不由语言定义。