Скажем, у нас есть два List<T>
.Первый - это список итогов продаж:
class SalesTotals
{
public Guid EmpID { get; set; }
public string EmpName { get; set; }
public decimal? TotalSales { get; set; }
}
Затем у нас есть еще один список продаж по годам:
class YearlySales
{
public Guid EmpID { get; set; }
public short SalesYear { get; set; }
public decimal? YearlyTotals { get; set; }
}
Они используются вместе для создания отчета "кросс-таблицы", которыйперечисляет общий объем продаж каждого сотрудника, за которым следует столбец для каждого года с указанием соответствующих годовых продаж.Это будет выглядеть примерно так:
| Name | Total | 2018 | 2017 | 2016 |
+------+-------+------+------+------+
| Joe | 70 | 20 | | 50 |
| Sam | 60 | 30 | 20 | 10 |
| Fred | 50 | 30 | | 20 |
| Bob | 40 | 10 | 15 | 15 |
По умолчанию отчет сортируется по TotalSales (без проблем).Но если мы хотим отсортировать по отдельным годам, все становится сложнее.Сортировка по 2017 году (затем по общему количеству):
| Name | Total | 2018 | 2017 | 2016 |
+------+-------+------+------+------+
| Sam | 60 | 30 | 20 | 10 |
| Bob | 40 | 10 | 15 | 15 |
| Joe | 70 | 20 | | 50 |
| Fred | 50 | 30 | | 20 |
Я предполагаю, что мы хотим (влево) Join
эти два List<T>
s на EmpID
, where SalesYear == <year to sort by>
, затем OrderBy
YearlyTotals, TotalSales
(поскольку YearlyTotals может не существовать в течение определенного года, и мы все еще хотим, чтобы в этом случае был какой-то порядок).Поэтому мы также должны учитывать, что может не быть записи за этот год для присоединения (поэтому это должно быть левое соединение).
Если бы я писал SQL, это выглядело бы примерно так:
SELECT ST.EmpID, ST.EmpName, ST.TotalSales
FROM SalesTotals AS ST
LEFT JOIN YearlySales AS YS ON ST.EmpID=YS.EmpID
WHERE YS.SalesYear=@SortBySalesYear OR YS.SalesYear IS NULL
ORDER BY YS.YearlySales DESC, ST.TotalSales DESC
Я недостаточно хорош с Линком (пока), чтобы понять это.На самом деле, я был практически не в состоянии (возможно, пытаясь сделать слишком много сразу, возможно, мне нужно разбить его на отдельные этапы, а не искать один вкладыш).
Итак,Есть ли способ сделать это с Linq?Или мне следует попробовать какой-то другой подход?
Примечание: все, что мне нужно, это сортировка по месту.Мне не нужен / не нужен другой тип List<T>
, возвращаемый здесь, просто отсортированный List<SalesTotals>
.
Редактировать: я предпочитаю Linq «Синтаксис запроса», так как он более интуитивен для меня (сильный SQLфон).Поэтому я предпочитаю ответ, используя синтаксис запроса, а не синтаксис метода.
Редактировать: Вот настройка теста:
class SalesTotals
{
public int EmpID { get; set; }
public string EmpName { get; set; }
public decimal? TotalSales { get; set; }
}
class YearlySales
{
public int EmpID { get; set; }
public short SalesYear { get; set; }
public decimal? YearlyTotals { get; set; }
}
class TestSort
{
public TestSort()
{
var st = new List<SalesTotals>
{
new SalesTotals() { EmpID = 1, EmpName = "Joe", TotalSales = 70 },
new SalesTotals() { EmpID = 2, EmpName = "Sam", TotalSales = 60 },
new SalesTotals() { EmpID = 3, EmpName = "Fred", TotalSales = 50 },
new SalesTotals() { EmpID = 4, EmpName = "Bob", TotalSales = 40 }
};
var ys = new List<YearlySales>
{
new YearlySales() { EmpID = 1, SalesYear = 2018, YearlyTotals = 20 },
new YearlySales() { EmpID = 2, SalesYear = 2018, YearlyTotals = 30 },
new YearlySales() { EmpID = 3, SalesYear = 2018, YearlyTotals = 30 },
new YearlySales() { EmpID = 4, SalesYear = 2018, YearlyTotals = 10 },
new YearlySales() { EmpID = 2, SalesYear = 2017, YearlyTotals = 20 },
new YearlySales() { EmpID = 4, SalesYear = 2017, YearlyTotals = 15 },
new YearlySales() { EmpID = 1, SalesYear = 2016, YearlyTotals = 10 },
new YearlySales() { EmpID = 2, SalesYear = 2016, YearlyTotals = 15 },
new YearlySales() { EmpID = 3, SalesYear = 2016, YearlyTotals = 50 },
new YearlySales() { EmpID = 4, SalesYear = 2016, YearlyTotals = 20 }
};
st = SortByYear(st, ys, 2017);
}
private List<SalesTotals> SortByYear(List<SalesTotals> salesTotals, List<YearlySales> yearlySales, short sortYear)
{
// return sorted salesTotals by sortYear using both salesTotals and yearlySales joined on EmpID
}
}