2012-06-20 80 views
2

假设我们有两个表Foo和Bar。对于Foos和Bars之间的多对多关系,我有一个关联表Foo_Bar。查询中的SQL动态

现在我基本上想要一个查询来选择匹配动态条数限制的Foos。我可以动态生成与加入适当数量的查询做到这一点:

SELECT * 
FROM Foo F INNER JOIN 
    Foo_Bar FB1 ON FB1.FooId = F.Id AND FB1.BarId= Y INNER JOIN 
    Foo_Bar FB2 ON FB2.FooId = F.Id AND FB2.BarId= Z INNER JOIN 
    --one inner join for each constraint 

我想知道是否有更简单的方法。我基本上要像这样的查询:

SELECT * 
FROM Foo F 
WHERE (Y, Z, ...) IN (SELECT BarId FROM Foo_Bar WHERE FooId = F.Id) 

当然,这不是有效的SQL,但我想知道如果动态查询是为了达到预期的效果的唯一合理的可移植的方法。

+1

你可以做'JOIN foo_bar这样FB1 ON FB1.FooId = F.Id WHERE FB1.BarId IN(Y,Z, ....)' – Lamak

+0

不完全。见下面我对Dancrumb的回复。 – naasking

回答

1

我假设你想要一个关系部门查询。看到这个问题有很多方法可以做到这一点:How to filter SQL results in a has-many-through relation

也有@欧文的回答(为Postrgres)性能测试,你会发现,动态的方式(使用很多连接或许多EXISTS子查询或许多IN子查询)比仅使用变量表或列表的静态查询执行得更快。

在您的服务器上进行测试,并确认您的数据。 MySQL例如在IN子查询中存在一些性能问题,所以我期望它在JOIN版本中执行得更快。

这里的“欧文1”查询,翻译成你的表:

SELECT f.* 
FROM Foo f 
JOIN (
    SELECT FooId 
    FROM Foo_Bar 
    WHERE BarId IN (Y, Z, ...)    --- your list or table here 
    GROUP BY FooId 
    HAVING COUNT(*) = @N      --- the size of this list or table 
    ) fb ON fb.FooId = f.Id; 
+0

您链接到的令人感兴趣的线索。我确信必须有一种方法来使用简单的参数而不是动态sql来编写这种查询,我认为你已经很好地回答了这个挑战,所以谢谢! – naasking

1

此基础上你给的信息,下面的查询会得到你需要的数据:

SELECT * 
FROM Foo F INNER JOIN 
    Foo_Bar FB ON FB1.FooId = F.Id 
WHERE FB.BarId IN (Y, Z, ...) 
+0

您的建议匹配FB.BarId为Z或Y的所有记录或...我希望F的所有记录都有FB.BarId为Z和Y AND ...基本上是您提供的查询的对偶。 – naasking