我有以下 SQL 代码,我想转换为 Entity Framework Core 8 中的 Linq lambda 查询。
SELECT * FROM(
SELECT ROW_NUMBER() OVER (PARTITION BY StaffId,[Location] ORDER BY [Timestamp] DESC) AS rn, StaffId, Location, [Timestamp]
FROM CountryStaff
WHERE [Timestamp] >=
DATEADD(hour,-1, GETDATE())
AND [Location] = 'USA'
)x WHERE x.rn = 1
这是我的 Linq 代码。
var date = DateTime.UtcNow.AddHours(-1);
var filteredTransactions = CountryStaff
.Where(t => t.Location == "USA" && t.Timestamp >= date)
.OrderByDescending(t => t.Timestamp);
filteredTransactions
.OrderByDescending(t => t.Timestamp)
.Skip(0)
.Take(1)
.Select(t => new
{
StaffId = t.StaffId,
Location = t.Location,
Timestamp = t.Timestamp
}).ToList();
执行此代码时,它会被翻译如下并产生错误的结果
DECLARE @p0 NVarChar(1000) = 'USA'
DECLARE @p1 DateTime = '2024-02-28 06:25:22.590'
DECLARE @p2 Int = 0
DECLARE @p3 Int = 1
SELECT [t2].[StaffId], [t2].[Location], [t2].[Timestamp]
FROM (
SELECT [t1].[StaffId], [t1].[Timestamp], [t1].[Location], [t1].[ROW_NUMBER]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[Timestamp] DESC, [t0].[Timestamp] DESC) AS [ROW_NUMBER], [t0].[StaffId], [t0].[Timestamp], [t0].[Location]
FROM [CountryStaff] AS [t0]
WHERE ([t0].[Location] = @p0) AND ([t0].[Timestamp] >= @p1)
) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p2 + 1 AND @p2 + @p3
) AS [t2]
ORDER BY [t2].[ROW_NUMBER]
编辑
我尝试使用此代码。尽管翻译了不同的 sql 查询,但它运行良好。不幸的是,它需要 5 秒而不是 0.6 毫秒。
CountryStaff
.Where(t => t.Timestamp >= date && t.Location == "USA")
.GroupBy(t => new { t.StaffId, t.Location })
.Select(g => g.OrderByDescending(t => t.Timestamp).First())
.ToList();
试试这个
var currentTimeMinusOneHour = DateTime.UTC.AddHours(-1);
var result = CountryStaff
.Where(cs => cs.Timestamp >= currentTimeMinusOneHour && cs.Location == "USA")
.GroupBy(cs => new { cs.StaffId, cs.Location })
.Select(g => new
{
RowNumber = g.OrderByDescending(x => x.Timestamp)
.Select((x, index) => new { x, index })
.FirstOrDefault()?.index + 1,
StaffId = g.Key.StaffId,
Location = g.Key.Location,
Timestamp = g.Max(x => x.Timestamp)
})
.Where(x => x.RowNumber == 1)
.ToList();