【问题标题】:SQL "IN" CLAUSE Performance issueSQL "IN" CLAUSE 性能问题
【发布时间】:2015-05-04 02:19:23
【问题描述】:

我有一个简单的 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 语句?谢谢

【问题讨论】:

  • "如何让生成的 SQL 看起来更像原始的 sql 语句?" - 我怀疑他们会是一样的! IN 子句本质上是复合 OR。我建议你确切地告诉我们你想要达到的目标,而不是一个感知的解决方案。
  • 我尝试了原始语句和生成的语句。生成的语句运行速度慢了很多。
  • 这很奇怪,但是我重写了你的查询,我生成的 sql 语句是 ' WHERE (SUBSTRING(REPLACE([Extent1].[Name], N'.', N''), 0 + 1, 4) IN (N'ABCE', N'BCDS', N'EDSC', N'XDSD', N'EFSE')) AND (SUBSTRING(REPLACE([Extent1].[Name], N'. ', N''), 0 + 1, 4) 不为 NULL)'。你确定这是整个查询吗?您使用的是哪个 EF 版本?
  • 您使用的是 SQL Server 还是其他提供程序?

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


【解决方案1】:

我只用 linqpad 对其进行了测试,但我认为这会产生更有效的查询。

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

【讨论】:

  • @downvoter 也许你可以解释为什么你不赞成这个答案?
【解决方案2】:

这很奇怪,但是我重写了你的查询并且生成的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')");

【讨论】:

    【解决方案3】:

    我认为你不能(至少很容易)控制 sql 语句生成过程的这些细节。

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-19
        • 2022-07-23
        • 2021-08-21
        • 2023-03-27
        • 2012-01-18
        • 2013-09-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多