如何根据条件按 1 个表达式或 2 个表达式排序?
Posted
技术标签:
【中文标题】如何根据条件按 1 个表达式或 2 个表达式排序?【英文标题】:How to order by 1 expression or 2 expressions based on a condition? 【发布时间】:2018-05-31 23:45:33 【问题描述】:我在一个结果中显示企业和人员,并希望将它们一起订购。
伪代码:
if business name is not null
order by business name
else
order by first name then last name
我构建了 LINQ 查询,它连接到多个表(并且工作正常),大致如下所示。
var query = from x in ...
join business in dbContext.Businesses on ...
from businesses in bus.DefaultIfEmpty()
join person in dbContext.People on ...
from people in peo.DefaultIfEmpty()
select new Party
person.FirstName,
person.LastName,
business.Name,
;
我不知道如何编写一个 LINQ 表达式,如果记录是企业,则仅按企业名称排序,否则人名和姓氏。我能得到的最接近的是以下内容,其中始终包括按人的姓氏排序(即使对于企业也是如此)。
var result =
whereQuery
.OrderBy(x => x.BusinessName != null ? x.BusinessName : x.PersonFirstName)
.ThenBy(x => x.PersonLastName);
转换成 SQL:
ORDER BY CASE
WHEN [business].[Name] IS NOT NULL
THEN [business].[Name]
ELSE [person].[FirstName]
END, [person].[LastName]
我想要的是:
ORDER BY CASE
WHEN [business].[Name] IS NOT NULL
THEN [business].[Name]
ELSE [person].[FirstName], [person].[LastName]
END
这是我希望能够写的(显然错误部分的语法不正确):
var result =
whereQuery
.OrderBy(x => x.BusinessName != null ? x.BusinessName : x.PersonFirstName, x.PersonLastName);
从技术上讲,它并没有太大的区别(如果是企业,则人名和姓氏将为空,因此不应该影响顺序)。但 SQL 仍会尝试通过它不需要做的事情进行排序。
【问题讨论】:
【参考方案1】:var result =
whereQuery
.OrderBy(x => x.BusinessName != null ? x.BusinessName : x.PersonFirstName)
.ThenBy(x => x.BusinessName != null ? x.BusinessName : x.PersonLastName);
在BusinessName
不为空的情况下会有冗余的二阶排序,但查询分析器(解析 SQL 后的下一步)应该能够删除该冗余。
【讨论】:
我最喜欢这个,因为ThenBy
不会对企业造成伤害(正如您所提到的),而且您不需要修改查询本身。请注意,ThenBy
无论如何都只需要订购领带。
@DavidSpence 是的。查询分析器的输出是什么样的?
对不起,我按回车太快了。这会产生两个案例陈述,但正如你所说,可能有一些优化。我会检查一下。当 [o].[Name] IS NOT NULL THEN [o].[Name] ELSE [b].[LastName] END 时按大小写排序,当 [o].[Name] 不为 NULL THEN [o].[姓名] ELSE [b].[名字] END
@DavidSpence:当然,这些优化是由数据库而不是实体框架完成的。该 sql 将被发送到 rdbms。但即使数据库是愚蠢的,这也不会受到伤害。结果将是相同的,并且仅在领带上应用额外的排序(如果企业名称重复)。【参考方案2】:
像这样修改你的代码:
var query = from x in ...
join business in dbContext.Businesses on ...
from businesses in bus.DefaultIfEmpty()
join person in dbContext.People on ...
from people in peo.DefaultIfEmpty()
select new Party
Name = business.Name ?? person.FirstName,
person.LastName
;
var result = whereQuery
.OrderBy(x => x.Name)
.ThenBy(x => x.PersonLastName);
选择名称并确保它不为空,然后按此字段排序。
【讨论】:
我认为这相当于我的代码,除了空检查在不同的地方?看起来它仍将始终包含按人姓的顺序,即使对于企业也是如此。以上是关于如何根据条件按 1 个表达式或 2 个表达式排序?的主要内容,如果未能解决你的问题,请参考以下文章