【问题标题】:Order of Execution of Condition in a Where clauseWhere 子句中条件的执行顺序
【发布时间】:2016-02-11 06:44:33
【问题描述】:

我有以下带有 Or 条件的语句。我正在寻找两个条件都为真时的结果。

 var result = db.Result.FirstOrDefault(x=>(x.ID==50||x.ID==60)&&x.Name="XYZ");

如果我在结果表中有一行同时满足两个条件,即; x.ID=50x.ID=60。查询的结果是什么?

我已经在测试环境中进行了测试以获得结果。但我想确保无论数据库大小如何,执行顺序始终保持不变。正如我所读到的,where 子句使用某种索引来加快检索速度,该语句的执行过程是什么。

提供的查询只是一个示例,名称 ID 与表的唯一标识无关。

问题

如何对数据库执行检查?我希望它首先检查ID ==50 和失败检查ID==60 的结果。如果这是我的预期结果,上面给出的查询会完成我的任务吗?

回答后更新

我觉得有必要举一个更清楚的例子,这样问题就更容易理解了。 (如果此更新使现有答案无效,我真的很抱歉)

 var result = db.result.firstordefault(x=>(x.foreignkeyid == someval|| foreignkeyid == 123)&& x.Name=="XYZ");

还有我的数据库示例

ID  foreignkeyid    Name
1      123          XYZ
2    somevalue      XYZ
3    anothervalue   XYZ

在这种情况下,执行查询时,结果将返回带有 ID==1 的行,但我希望返回带有 ID==2 的行。

实现结果的最坏情况尝试

 var result = new Result();
 result =db.Result.firstordefault(x=>x.ID==somevalue&&x.name==xyz);
 if(result==null)
     var result = db.firstordefault(x=>x.ID ==123&& x.name==xyz);

【问题讨论】:

  • 您的查询正在检查 Name 是否为 XYZ,ID 是否为 50 或 60。它达到了您的要求。
  • 是的。我错过了我添加了那个条件。我将编辑问题以使其成为真实。
  • 有可能不满足特定条件。我即使尝试这种方式(foreignkeyid==somevalue &&name==XYZ)||(foreignkeyid==123&&name==XYZ)。但这也将等同于我猜的上述查询
  • 对于这种情况,它的优化器决定了查询的计划方式,所以如果它发现匹配记录的条件很早就被检索到,那么它将得到那个。因此,对此没有硬性规定。但是,您可以强制优化器使用 order by 子句检索记录,例如 order by ID desc limit 1

标签: c# mysql asp.net-mvc linq


【解决方案1】:

鉴于你的这个例子:

var result = db.result.firstordefault(x=>(x.foreignkeyid == someval|| foreignkeyid == 123)&& x.Name=="XYZ");

你要在其中fk = someval(fk:外键)的结果优先级,你可以这样做:

db.set.OrderBy(x => x != someval) // false actually comes before true
      .ThenBy(x => x != val2ndPriority)
      .FirstOrDefault(x => (x.fk == someval ||
                            x.fk == val2ndPriority ||
                            x.fk == leastPriorityVal) &&
                           x.Name == "XYZ");

如果你有很多“优先的 fk 值”,或者在编译时它们是未知的,你可以这样做:

var orderedEnum = db.set.OrderBy(x => x.Id);
foreach (var fk in fksByPriority)
    orderedEnum = orderedEnum.ThenBy(x => x != fk);
var result = orderedEnum.FirstOrDefault(x => fksByPriority.Contains(x.fk) &&
                                             x.Name == "XYZ");

我希望它是什么样子:

另一种不同的方法是获取所有可能相关的记录,然后在数据库之外运行类似的逻辑(您的 db Linq 查询通常在数据库内巧妙地运行):

var results = db.set.Where(x => x.Name == "XYZ" &&
                                fks.Contains(x.fk)).ToArray();
var highestPriorityResult =
    results.OrderBy(x => fksByPriority.IndexOf(x.fk)).FirstOrDefault();

最后,我想说的是,您的问题表明设计可能存在缺陷。我无法想象你为什么会遇到这种使用优先级外键过滤的问题。

【讨论】:

  • 如果 false 出现在 true 之前,那么我需要的行将在订购时放在最后,对吗?因为someval 是最高优先级的值。
  • 这就是为什么我使用!=而不是逻辑上正确的==(只是因为它比使用OrderByDescending更短。玩它看看你得到什么,你总是可以翻转比较或如果需要,请致电.Reverse()
  • 哦,是的。我错过了..哎呀!我明白了。。非常感谢。
猜你喜欢
  • 2023-01-10
  • 1970-01-01
  • 1970-01-01
  • 2017-02-08
  • 2013-05-18
  • 2022-01-20
  • 2015-02-25
  • 2011-09-07
  • 1970-01-01
相关资源
最近更新 更多