这个例子中效率最高的SQL

时间:2013-04-30 15:17:35

标签: sql

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

我有一个搜索屏幕,其中包含固定玩具名称的下拉列表。 如果一个人的玩具总数的一部分匹配,则会发现搜索。

例如,人名=鲍勃有玩具:娃娃,汽车,房子,帽子

搜索人名= bob和toys = doll,hat。

我想要归还鲍勃和他的所有玩具,而不仅仅是寻找玩具(娃娃,帽子)。 Bob被发现是因为他的玩具的一部分是匹配的。

我不知道最有效/最少db调用的方法是什么。 我可以搜索bob并获取他所有的玩具,然后解析结果集以查看搜索到的玩具是否找到匹配,但这似乎是错误的,db调用可以返回找不到匹配的行(那似乎不对?)。

2 个答案:

答案 0 :(得分:2)

行,

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');

Fiddle Here


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

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
        );

将有效地工作。

Updated Fiddle

答案 1 :(得分:0)

这是使用子查询并在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 Fiddle Demo