luthier Ответов: 2

Vb.net группировка по максимальному значению записей...


Source Table

Ct	Ad	Qua	Price
A	1	34	700
A	2	53	600
A	3	654	500
B	3	45	1200
B	53	434	500
B	5	63	200
B	3	35	200
B	5	63	100 
C	31	45	2200
C	53	434	500
C	51	63	200
C	32	235	200
C	52	63	100



Result Table
Ct	Ad	Qua	Price 
A	1	34	700
B	3	45	1200
C	31	45	2200 


Что я уже пробовал:

Я хочу сделать запрос linq для этой таблицы результатов в vb.net.
Поле "Ct" должно быть сгруппировано, и я получу в этой группе максимум "цена".

Мой английский не очень хорош. Большое спасибо.

2 Ответов

Рейтинг:
16

Maciej Los

Проверить это:

Dim dt As DataTable = New DataTable()
dt.Columns.AddRange(New DataColumn(){
		New DataColumn("Ct", Type.GetType("System.String")),
		New DataColumn("Ad", Type.GetType("System.Int32")),
		New DataColumn("Qua", Type.GetType("System.Int32")),
		New DataColumn("Price", Type.GetType("System.Int32"))})
dt.Rows.Add(New Object(){"A", 1, 34, 700})
dt.Rows.Add(New Object(){"A", 2, 53, 600})
dt.Rows.Add(New Object(){"A", 3, 654, 500})
dt.Rows.Add(New Object(){"B", 3, 45, 1200})
dt.Rows.Add(New Object(){"B", 53, 434, 500})
dt.Rows.Add(New Object(){"B", 5, 63, 200})
dt.Rows.Add(New Object(){"B", 3, 35, 200})
dt.Rows.Add(New Object(){"B", 5, 63, 100})
dt.Rows.Add(New Object(){"C", 31, 45, 2200})
dt.Rows.Add(New Object(){"C", 53, 434, 500})
dt.Rows.Add(New Object(){"C", 51, 63, 200})
dt.Rows.Add(New Object(){"C", 32, 235, 200})
dt.Rows.Add(New Object(){"C", 52, 63, 100})

Dim result = dt.AsEnumerable() _
	.GroupBy(Function(x) x.Field(Of String)("Ct")) _
	.Select(Function(grp) New With _
	{ _
		.Ct = grp.Key, _
		.Ad = grp.OrderByDescending(Function(x) x.Field(Of Integer)("Price")) _
			.Select(Function(x) x.Field(Of Integer)("Ad")).FirstOrDefault(), _
		.Qua = grp.OrderByDescending(Function(x) x.Field(Of Integer)("Price")) _
			.Select(Function(y) y.Field(Of Integer)("Qua")).FirstOrDefault(), _
		.Price = grp.Max(Function(z) z.Field(Of Integer)("Price")) _
	}) _
	.ToList()

Console.WriteLine(String.Format("{0} {1} {2} {3}", "Ct", "Ad", "Qua", "Price"))
For Each item In result
	Console.WriteLine(String.Format("{0} {1} {2} {3}", item.Ct, item.Ad, item.Qua, item.Price))
Next


Richard Deeming

Вероятно, было бы лучше отсортировать сгруппированные строки по убыванию цены и взять первую строку, а не бегать Max три раза, используя его для фильтрации сгруппированных строк, а затем проецируя из него один столбец. :)

Maciej Los

Ты, как всегда, прав, Ричард.
[РЕДАКТИРОВАТЬ]
Обновлено!
Я хотел поделиться решением, отличным от вашего.

luthier

Большое спасибо. Ты настоящий герой!

Maciej Los

Всегда пожалуйста.

Рейтинг:
10

Richard Deeming

Другое решение:

Установка:

Dim dt As DataTable = New DataTable()
dt.Columns.AddRange(New DataColumn(){
    New DataColumn("Ct", GetType(String)),
    New DataColumn("Ad", GetType(Integer)),
    New DataColumn("Qua", GetType(Integer)),
    New DataColumn("Price", GetType(Integer))})
		
dt.Rows.Add(New Object(){"A", 1, 34, 700})
dt.Rows.Add(New Object(){"A", 2, 53, 600})
dt.Rows.Add(New Object(){"A", 3, 654, 500})
dt.Rows.Add(New Object(){"B", 3, 45, 1200})
dt.Rows.Add(New Object(){"B", 53, 434, 500})
dt.Rows.Add(New Object(){"B", 5, 63, 200})
dt.Rows.Add(New Object(){"B", 3, 35, 200})
dt.Rows.Add(New Object(){"B", 5, 63, 100})
dt.Rows.Add(New Object(){"C", 31, 45, 2200})
dt.Rows.Add(New Object(){"C", 53, 434, 500})
dt.Rows.Add(New Object(){"C", 51, 63, 200})
dt.Rows.Add(New Object(){"C", 32, 235, 200})
dt.Rows.Add(New Object(){"C", 52, 63, 100})
Запрос:
Dim result As DataTable = dt.AsEnumerable().
    GroupBy(Function(r) r.Field(Of String)("Ct"), Function(key, rows) rows.OrderByDescending(Function(r) r.Field(Of Integer)("Price")).First()).
    CopyToDataTable()


Maciej Los

5ed!

luthier

Я не мог поверить этому вопросу. Пока не увидел результат. Ты тоже герой. Большое вам спасибо!