我有下一个代码,采用DB中元素的Last和Pre-Last参数:
var result = _context.Contacts.Where(conts => conts.CreatorUserId == _userManager.GetUserId(this.User))
.Select(conts => new
{
conts.ID,
conts.Mobile,
conts.Email,
conts.Facebook,
conts.StateId,
conts.CreatorUserId,
conts.Birthday,
conts.Description,
conts.Name,
conts.Photo,
conts.SecondName,
Tags = conts.Tags.Select(d=> d.UserTag.Emoji),
NpaId = conts.NpaInfo.NpaId,
PartnerPvPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.MyPV).FirstOrDefault(),
GroupPvPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.GroupPV).FirstOrDefault(),
LevelPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault(),
PartnerPv = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Take(1).Select(x => x.MyPV).FirstOrDefault(),
Level = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault(),// conts.NpaInfo.PerformanceBonusLevelId,
GroupPv = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Take(1).Select(x => x.GroupPV).FirstOrDefault(),
EntryDate = conts.NpaInfo.EntryDate,
ExpirationDate = conts.NpaInfo.ExpirationDate
});
实际上是该部分:
PartnerPvPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.MyPV).FirstOrDefault(),
GroupPvPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.GroupPV).FirstOrDefault(),
LevelPrev = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault()
在1个请求中转换为这样的内容(仅显示一个块的一部分):
SELECT TOP(1) [t0].[MyPV]
FROM (
SELECT [x0].[MyPV], [x0].[DataMonth]
FROM [NpaDatas] AS [x0]
WHERE [conts.NpaInfo].[ID] = [x0].[NpaInfoId]
ORDER BY [x0].[DataMonth] DESC
OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY
) AS [t0]
ORDER BY [t0].[DataMonth] DESC
) AS [PartnerPvPrev], (
SELECT TOP(1) [t1].[GroupPV]
FROM (
SELECT [x1].[GroupPV], [x1].[DataMonth]
FROM [NpaDatas] AS [x1]
WHERE [conts.NpaInfo].[ID] = [x1].[NpaInfoId]
ORDER BY [x1].[DataMonth] DESC
OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY
) AS [t1]
ORDER BY [t1].[DataMonth] DESC
) AS [GroupPvPrev], (
SELECT TOP(1) [t2].[PerformanceBonusLevelId]
FROM (
SELECT [x2].[PerformanceBonusLevelId], [x2].[DataMonth]
FROM [NpaDatas] AS [x2]
WHERE [conts.NpaInfo].[ID] = [x2].[NpaInfoId]
ORDER BY [x2].[DataMonth] DESC
OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY
) AS [t2]
ORDER BY [t2].[DataMonth] DESC
) AS [LevelPrev]
我不想多次重复同一部分:
conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1)
所以,如果我这样做:
PrevBuffer = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Skip(1).Take(1).Select(
param => new
{
param.MyPV,
param.GroupPV,
param.PerformanceBonusLevelId
}
),
它将在输出中为每一行显示许多单独的请求,例如:
SELECT [x0].[MyPV], [x0].[GroupPV], [x0].[PerformanceBonusLevelId]
FROM [NpaDatas] AS [x0]
WHERE @_outer_ID1 = [x0].[NpaInfoId]
ORDER BY [x0].[DataMonth] DESC
OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY
这部分也一样:
Tags = conts.Tags.Select(d=> d.UserTag.Emoji)
将获得多个选择,例如:
SELECT [d.UserTag].[Emoji]
FROM [ContactTags] AS [d]
LEFT JOIN [UserTags] AS [d.UserTag] ON [d].[UserTagId] = [d.UserTag].[ID]
WHERE @_outer_ID = [d].[ContactId]
可以通过某种方式对其进行优化吗?
答案 0 :(得分:1)
做这样的事情将大大改善查询。
var result = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth).Take(2).ToArray();
PartnerPvPrev = result.Skip(1).Take(1).Select(x => x.MyPV).FirstOrDefault();
GroupPvPrev = result.Skip(1).Take(1).Select(x => x.GroupPV).FirstOrDefault();
LevelPrev = result.Skip(1).Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault();
PartnerPv = result.Take(1).Select(x => x.MyPV).FirstOrDefault();
Level = result.Take(1).Select(x => x.PerformanceBonusLevelId).FirstOrDefault();
GroupPv = result.Take(1).Select(x => x.GroupPV).FirstOrDefault();
答案 1 :(得分:1)
您应该首先选择重复部分,然后在后续查询中使用它们。使用let
关键字,这在查询语法中要容易得多:
var result = from conts in _context.Contacts
where conts.CreatorUserId == _userManager.GetUserId(this.User)
let monthsSorted = conts.NpaInfo.NpaData.OrderByDescending(x => x.DataMonth)
let firstMonth = monthsSorted.FirstOrDefault()
let prevMonth = monthsSorted.Skip(1).FirstOrDefault()
select new
{
conts.ID,
conts.Mobile,
conts.Email,
conts.Facebook,
conts.StateId,
conts.CreatorUserId,
conts.Birthday,
conts.Description,
conts.Name,
conts.Photo,
conts.SecondName,
Tags = conts.Tags.Select(d=> d.UserTag.Emoji),
NpaId = conts.NpaInfo.NpaId,
PartnerPvPrev = prevMonth.MyPV,
GroupPvPrev = prevMonth.GroupPV,
LevelPrev = prevMonth.PerformanceBonusLevelId,
PartnerPv = firstMonth.MyPV,
GroupPv = firstMonth.GroupPV,
Level = firstMonth.PerformanceBonusLevelId,
EntryDate = conts.NpaInfo.EntryDate,
ExpirationDate = conts.NpaInfo.ExpirationDate
};
答案 2 :(得分:0)
您应该使用GroupBy:
class Program
{
static void Main(string[] args)
{
Conts conts = new Conts();
List<NpaDatas> data = conts.NpaInfo.NpaDatas
.OrderByDescending(x => x.DataMonth)
.GroupBy(x => x.DataMonth).Select(x => x.FirstOrDefault()).ToList();
//To get the second latest use followng
NPaDatas results = data.Skip(1).FirstOrDefault();
}
}
public class NpaDatas
{
public string NpaInfoId { get; set; }
public DateTime DataMonth { get; set; }
public PV PartnerPv { get; set; }
public PV PerformanceBonusLevelId { get; set; }
public PV GroupPv { get; set; }
}
public class PV
{
//data not specified
}
public class Conts
{
public NpaInfo NpaInfo { get; set; }
}
public class NpaInfo
{
public string ID { get; set; }
public List<NpaDatas> NpaDatas { get; set; }
}