我们知道,在sql中使用IN让我们的where子句可以规定多个值。当需要从一个集合中查询包含某几个值的记录的时候,通常我们会选择使用IN来实现,其实,使用JOIN也可以实现这样的功能,而且性能要比IN好。我会从以下几个方面来进行总结。

  1. 使用IN和JOIN的性能对比
  2. EF中如何使用JOIN来代替IN

使用IN和JOIN的性能对比

  首先来看一段sql语句,然后通过执行计划来比较它们之间的性能。

使用IN和JOIN查询的代码:

 下面是它们的执行计划:

通过执行计划,可以看到使用JOIN的性能要比IN好。

EF中如何使用JOIN来代替IN

  我们在使用EF的时候, 会有很多像下面这样的查询。

1 List<int> productIds = new List<int>
2 {
3     15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
4 };
5 using (var db = new PackageFHContext())
6 {
7     var containerResult = db.ProductMasterSet.Where(p => productIds.Contains(p.ProductID));
8 }

实际上,这种写法生成的sql代码就是使用了IN,下面是使用Sql Server Profiler监测到的结果。

SELECT …..
FROM [dbo].[Pkg_ProductMaster] AS [Extent1]
WHERE [Extent1].[ProductID] IN (15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30);

那么,我们怎样来实现JOIN来代替IN呢,我们可以借助SQL CLR函数来实现,代码如下。

 1 List<int> productIds = new List<int>
 2 {
 3     15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
 4 };
 5 using (var db = new PackageFHContext())
 6 {
 7     var joinResult = from p in db.ProductMasterSet
 8      join c in db.CLR_Split(string.Join(",", productIds), ",", true) on p.ProductID.ToString() equals c.id
 9      select p;
10 }

这里使用了SQL CLR的Split函数将list处理成一个表后再关联过滤的,生成的SQL语句如下。

Select ……
FROM  [dbo].[Pkg_ProductMaster] AS [Extent1]
    INNER JOIN [dbo].[CLR_Split](@input, @delimiter, @isRemoveEmptyEntries) AS [Extent2] ON  CAST( [Extent1].[ProductID] AS nvarchar(max)) = [Extent2].[id]
    WHERE 58 = [Extent1].[DepartureCityID];

 

posted on 2015-03-04 17:52  永远的麦子  阅读(3932)  评论(1编辑  收藏  举报