SQL "IN" 条款性能问题
SQL "IN" CLAUSE Performance issue
我有一个简单的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 语句?谢谢
我认为您是在比较字符数组而不是字符串。试试这个
Employees.Where(x => new string[] { "ABCE", "BCDS", "EDSC", "XDSD", "EFSE" }
.Contains((x.EmployeeName.Replace(".", "").Substring(0, 4).ToString())));
我只使用 linqpad 对其进行了测试,但我认为这会生成更高效的查询。
var result = from record in Employee
let name = record.EmployeeName.Replace( ".", "" ).Substring( 0, 4 )
where new[] { "ABCE", "BCDS", [...] }.Contains( name )
select record;
这很奇怪,但我重写了您的查询并生成了 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')");
我认为您无法(至少,很容易)控制 sql 语句生成过程的此类细节。
但是,如果您正在寻找可能的最佳查询,我会尝试使用 LIKE
运算符(通过在您的 LINQ 查询中使用一系列 .StartsWith
条件).
LIKE
可以使用 sql 索引,这可能不会发生在 SUBSTRING
和 REPLACE
.
中
我有一个简单的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 语句?谢谢
我认为您是在比较字符数组而不是字符串。试试这个
Employees.Where(x => new string[] { "ABCE", "BCDS", "EDSC", "XDSD", "EFSE" }
.Contains((x.EmployeeName.Replace(".", "").Substring(0, 4).ToString())));
我只使用 linqpad 对其进行了测试,但我认为这会生成更高效的查询。
var result = from record in Employee
let name = record.EmployeeName.Replace( ".", "" ).Substring( 0, 4 )
where new[] { "ABCE", "BCDS", [...] }.Contains( name )
select record;
这很奇怪,但我重写了您的查询并生成了 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')");
我认为您无法(至少,很容易)控制 sql 语句生成过程的此类细节。
但是,如果您正在寻找可能的最佳查询,我会尝试使用 LIKE
运算符(通过在您的 LINQ 查询中使用一系列 .StartsWith
条件).
LIKE
可以使用 sql 索引,这可能不会发生在 SUBSTRING
和 REPLACE
.