关于SelectStringJoin拼接字符串排序问题 返回

SqlSugar 处理完成
2 246
该叫什么 Zero 发布于2025/11/21
悬赏:0 飞吻

在mysql中,GROUP_CONCAT 可以指定排序字段规则,如下:

GROUP_CONCAT([DISTINCT] 字段名 [ORDER BY 排序字段 ASC/DESC, ...] [SEPARATOR '分隔符'])


完整语句如下:

SELECT group_concat(`number` ORDER BY `is_default` DESC, `id` SEPARATOR ',')FROM `user` `p`WHERE (`p`.`user_id` = 1942);


目前SelectStringJoin方法的定义如下:

 public string SelectStringJoin(Func<T, string> expression, string separator) => (string) null;

从上面可以看,不能指定排序,有什么替代办法


以下是示例代码,需求很简单,有用户表和电话表,将电话表中多个电话拼接,并将默认电话放在第一位,最终输出用户列表

var query = dbContext.Db.Queryable<User>() 

               .Where(user => user.CompanyId == currentId)

               .OrderBy(user => user.Id, OrderByType.Asc)

.Select((user) => new UserListItemOutDTO()

                {

                    Id = user.Id,

                    Name = user.Name,

                    Mobile = SqlFunc.Subqueryable<UserPhone>().Where(p=>p.UserId == user.Id).OrderByDesc(p=>p.IsDefault).OrderBy(p=>p.Id).SelectStringJoin(p=>p.Phone, ","),

                }).ToList()


热忱回答2

  • fate sta fate sta VIP0
    2025/11/21

    好的我看一下。

    0 回复
  • Zero Zero VIP0
    2025/11/21

    自己研究了一下,AI挺靠谱的,有两种法办可以实现:

    方案1:
    使用 MappingColumn 函数,手写SQL排序条件

    优点:少联一张表,性能可能高一点

    缺少:兼容性差,仅支持mysql,其他数据库不兼容

    var query = dbContext.Db.Queryable<User>() 

                   .Where(user => user.CompanyId == currentId)

                   .OrderBy(user => user.Id, OrderByType.Asc)

    .Select((user) => new UserListItemOutDTO()

                    {

                        Id = user.Id,

                        Name = user.Name,

                        Mobile = SqlFunc.Subqueryable<UserPhone>().Where(p=>p.UserId == user.Id).SelectStringJoin(p=> SqlFunc.MappingColumn<string>($"{p.Phone}  ORDER BY {p.IsDefault} DESC , {p.Id} ASC"), ",")   这里使用MappingColumn手写SQL排序条件

                    }).ToList()


    方案2:

    联表查询第一个默认电话,再用子查询查非默认电话,再拼接起来

    优点:兼容性好,理论上比手写SQL要强一些

    缺少:多联一张表,性能可能低一点

    var query = dbContext.Db.Queryable<User, Phone>((user, phone) => new object[]{ JoinType.Left, user.Id == phone.UserId && phone.IsDefault == true } )    这里联表查第一个默认电话

                   .Where(user => user.CompanyId == currentId)

                   .OrderBy(user => user.Id, OrderByType.Asc)

    .Select((user) => new UserListItemOutDTO()

                    {

                        Id = user.Id,

                        Name = user.Name,

                        Mobile = SqlFunc.MergeString(phone.Phone, ",", SqlFunc.Subqueryable<UserPhone>().Where(p=>p.UserId == user.Id && !p.IsDefault).SelectStringJoin(p=> p.Phone, ",")这里为两部分,内部子查询只查非默认电话并拼接,外层再将默认电话和非默认电话拼接,这样可以保证默认电话一定在第一位

                    }).ToList()



    0 回复