Преобразование SQL Rank() в LINQ или альтернативное
У меня есть оператор SQL, который работает по желанию/ожиданию. Однако я хотел бы перевести его в оператор LINQ (Lambda??), чтобы он соответствовал остальной части моего DAL. Однако я не могу понять, как имитировать Rank() в LINQ.
Причина, по которой я разместил ее здесь, что, возможно, является ошибкой, заключается в том, чтобы увидеть, есть ли у кого-либо альтернатива выражению Rank()
, чтобы я мог переключиться. Альтернативно, если есть способ представления Rank()
в LINQ, который также будет оценен.
USE CMO
SELECT vp.[PersonID] AS [PersonId]
,ce.[EnrollmentID]
,vp.[FirstName]
,vp.[LastName]
,ce.[EnrollmentDate]
,ce.[DisenrollmentDate]
,wh.WorkerCategory
FROM [dbo].[vwPersonInfo] AS vp
INNER JOIN
(
[dbo].[tblCMOEnrollment] AS ce
LEFT OUTER JOIN
(
SELECT *
,RANK()OVER(PARTITION BY EnrollmentID ORDER BY CASE WHEN EndDate IS NULL THEN 1 ELSE 2 END, EndDate DESC, StartDate DESC) AS whrank
FROM [dbo].[tblWorkerHistory]
WHERE WorkerCategory = 2
) AS wh
ON ce.[EnrollmentID] = wh.[EnrollmentID] AND wh.whrank = 1
)
ON vp.[PersonID] = ce.[ClientID]
WHERE (vp.LastName NOT IN ('Client','Orientation','Real','Training','Matrix','Second','Not'))
AND (
(wh.[EndDate] <= GETDATE())
OR wh.WorkerCategory IS NULL
)
AND (
(ce.[DisenrollmentDate] IS NULL)
OR (ce.[DisenrollmentDate] >= GetDate())
)
Ответы
Ответ 1
Вот пример, который показывает, как я смоделировал Rank() в Linq:
var q = from s in class.student
orderby s.Age descending
select new {
Name = s.name,
Rank = (from o in class.student
where o.mark > s.mark
select o).Count() + 1
};
Ответ 2
LINQ имеет встроенную ранговую функциональность, но не в синтаксисе запроса. При использовании синтаксиса метода большинство функций linq входят в две версии: нормальную и одну с поставленным рангом.
Простой пример, который выбирает только каждого другого ученика, а затем добавляет индекс в результирующую последовательность к результату:
var q = class.student.OrderBy(s => s.studentId).Where((s, i) => i % 2 == 0)
.Select((s,i) => new
{
Name = s.Name,
Rank = i
}
Ответ 3
Если вы хотите имитировать ранг, вы можете использовать следующий запрос linq.
var q = (from s in class.student
select new
{
Name = s.Name,
Rank = (from o in class.student
where o.Mark > s.Mark && o.studentId == s.studentId
select o.Mark).Distinct().Count() + 1
}).ToList();
вы можете использовать порядок, например:
var q = (from s in class.student
orderby s.studentId
select new
{
Name = s.Name,
Rank = (from o in class.student
where o.Mark > s.Mark && o.studentId == s.studentId
select o.Mark).Distinct().Count() + 1
}).ToList();
но порядок не имеет значения в этом запросе.
Ответ 4
На основе ответа от @Totero, но с реализацией lamda.
Высший балл = более высокий ранг.
var rankedData = data.Select(s => new{
Ranking = data.Count(x => x.Value > s.Value)+1,
Name = s.Key,
Score = s.Value});
Для этого ввода:
{ 100, 100, 98, 97, 97, 97, 91, 50 }
Вы получите этот вывод:
- Оценка: Ранг
- 100: 1
- 100: 1
- 98: 3
- 97: 4
- 97: 4
- 97: 4
- 91: 6
- 50: 7