关于SelectStringJoin拼接字符串排序问题 返回
在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 VIP0
2025/11/21好的我看一下。
0 回复 -
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 回复