繁体   English   中英

此示例中最有效的SQL

[英]Most efficient SQL for this example

Table A: Person: id, name
Table B: Toys: id, person_id, toy_name

我有一个搜索屏幕,其中包含固定玩具名称的下拉列表。 如果匹配一个人的玩具的总子集,则会找到一个搜索。

例如,一个人名字=鲍勃的人有玩具:洋娃娃,汽车,房子,帽子

搜索人员姓名=鲍勃,玩具=娃娃,帽子。

我想退回鲍勃和他所有的玩具,而不仅仅是寻找的玩具(娃娃,帽子)。 发现鲍勃是因为他的玩具的一部分是火柴。

我不知道最有效/最少的数据库调用该方法的方式。 我可以搜索bob并获取所有他的玩具,然后解析结果集以查看搜索到的玩具是否找到了匹配项,但这似乎是错误的,db调用可能会返回未找到匹配项的行(似乎错了吗?)。

好的,

select
  p.id,
  p.name, 
  t.id as toyid, 
  t.toy_name
from 
     person p
  join
     toys t
        on p.id = t.person_id
where
     p.id in (
        select person_id from toys where toy_name = 'doll'
        intersect
        select person_id from toys where toy_name = 'hat');

小提琴在这里


如果您进一步规范化架构,

create table Person
(
    Id int,
    Name varchar(100)
);

create table Toy
(
    Id int, 
    Name varchar(100)
);

create table PersonToy
(
    Id int,
    PersonId int,
    ToyId int
);

它应该使问题的复杂性更加清晰。 它还将节省一些空间。 形式的声明,

select
            p.Name PersonName,
            t.Name ToyName
    from
            Person p
        join
            PersonToy pt
                on pt.PersonId = p.Id
        join
            Toy t
                on t.Id = pt.ToyId
    where
        p.Id in
        (
            select PersonId from PersonToy where ToyId = 1
            intersect
            select PersonId from PersonToy where ToyId = 4
        );

将有效地工作。

更新小提琴

这是使用子查询并检查HAVING子句中Hat和Doll是否存在的一种方法:

select p.id, p.name, 
  t.id as toyid, t.name as toyname
from person p
  inner join toys t on p.id = t.person_id
  inner join (
    select person_id
    from toys 
    group by person_id
    having sum(name = 'hat') > 0 and
      sum(name = 'doll') > 0
    ) t2 on p.id = t2.person_id

SQL小提琴演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM