如何根据条件按 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 个表达式排序?的主要内容,如果未能解决你的问题,请参考以下文章

请问excel的if函数,是这种形式if(条件1,条件2,)不是应该3个条件吗?该怎么执行?谢谢各位!

条件 .NET 正则表达式

循环结构

[蒟蒻修炼计划][模板] 2-SAT

MySQLDQL之排序查询

进阶3:排序查询