SQL" IN"条款性能问题

时间:2015-05-04 02:19:24

标签: c# sql linq linq-to-entities

我有一个简单的SQL语句:

select * from Employee 
where LEFT(REPLACE(EmployeeName,'.',''),4) IN ('ABCE', 'BCDS', 'EDSC', 'XDSD', 'EFSE')

我正试图在Linq中做到这一点:

Employees.Where(x => new[] { "ABCE", "BCDS", "EDSC", "XDSD", "EFSE" }.Contains((x.EmployeeName.Replace(".", "").Substring(0, 4))));

但它生成的SQL语句效率不高。每次更新EmployeeName,然后再与字符串进行比较,而不只是一次:

SELECT 
[Extent1].[EmployeeID] AS [EmployeeID], 
[Extent1].[EmployeeName] AS [EmployeeName], 
[Extent1].[EmployeeTypeID] AS [EmployeeTypeID], 
[Extent1].[Active] AS [Active]
FROM [dbo].[Employee] AS [Extent1]
WHERE (N'ABCE' = (SUBSTRING(REPLACE([Extent1].[EmployeeName], N'.', N''), 0 + 1, 4))) 
OR (N'BCDS' = (SUBSTRING(REPLACE([Extent1].[EmployeeName], N'.', N''), 0 + 1, 4))) 
OR (N'EDsC' = (SUBSTRING(REPLACE([Extent1].[EmployeeName], N'.', N''), 0 + 1, 4))) 
OR (N'XDSs' = (SUBSTRING(REPLACE([Extent1].[EmployeeName], N'.', N''), 0 + 1, 4))) 
OR (N'EFSE' = (SUBSTRING(REPLACE([Extent1].[EmployeeName], N'.', N''), 0 + 1, 4)))

如何使生成的SQL看起来更像原始的sql语句?感谢

4 个答案:

答案 0 :(得分:2)

我只用linqpad测试过它,但我认为这会产生更有效的查询。

var result = from record in Employee
             let name = record.EmployeeName.Replace( ".", "" ).Substring( 0, 4 )
             where new[] { "ABCE", "BCDS", [...] }.Contains( name )
             select record;

答案 1 :(得分:1)

这很奇怪,但我重写了你的查询并生成了sql语句

WHERE (SUBSTRING(REPLACE([Extent1].[EmployeeName], N'.', N''), 0 + 1, 4) IN (N'ABCE', N'BCDS', N'EDSC', N'XDSD', N'EFSE')) AND (SUBSTRING(REPLACE([Extent1].[Name], N'.', N'')

我想这取决于使用的数据库和框架(在我的情况下是SQL Server 2008和EF)。

如果您使用EF,则可以强制EF使用您的sql语句

context.Set<Employee>().SqlQuery("select * from Employee where LEFT(REPLACE(EmployeeName,'.',''),4) IN ('ABCE', 'BCDS', 'EDSC', 'XDSD', 'EFSE')");

答案 2 :(得分:1)

我认为你不能(轻松地,至少)控制sql语句生成过程的这些细节。

但是,如果您正在寻找最好的可能性查询,我会尝试LIKE运算符(通过在LINQ查询中使用.StartsWith条件的系列)。

LIKE可以使用sql索引,SUBSTRINGREPLACE可能不会发生这种情况。

答案 3 :(得分:0)

我认为你正在比较一个字符数组而不是字符串。试试这个

Employees.Where(x => new string[] { "ABCE", "BCDS", "EDSC", "XDSD", "EFSE" }
         .Contains((x.EmployeeName.Replace(".", "").Substring(0, 4).ToString())));