csrss Ответов: 2

Сводной таблицы, используя LINQ


Всем привет. У меня есть такой стол:
------------
name | value
------------
n1   | v1
n2   | v2
n3   | v3
------------

Вот что нужно сделать:
------------
n1 | n2 | n3
------------
v1 | v2 | v3
------------

Дело в том, что таблица-это реальная таблица MSSQL, находящаяся в базе данных. В настоящее время я поворачиваю его с помощью T-SQL Pivot, но мне нужно сделать это с помощью LINQ. Кроме того, новая таблица должна быть отсортирована как обычная таблица.
Так возможно ли это вообще? Если это так - есть ли кто-нибудь, кто знает, как это сделать? Кстати, здесь все динамично, а динамический sql используется для T-SQL, столбцы динамичны и т. д.

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

Я читал, наверное, все в сети, как делать сводные таблицы, но пока ничего не получалось.

Maciej Los

Там нет данных, по которым данные могут быть развернуты (сгруппированы).
:(

2 Ответов

Рейтинг:
2

Maciej Los

Взгляните на приведенный ниже пример (созданный в LinqPad):

void Main()
{
	DataTable srcdt = GetInitialData();
	List<KeyValuePair<string, string>> data = srcdt.AsEnumerable()
		.Select(x=>new KeyValuePair<string, string>(x[0].ToString(), x[1].ToString()))
		.ToList();
	
	DataTable dstdt = new DataTable();
	List<string> cols = data.Select(x=> x.Key).Distinct().ToList();
	dstdt.Columns.AddRange(cols.Select(x=>new DataColumn(x, typeof(string))).ToArray());

	if(cols.Count != srcdt.Rows.Count)
		Console.WriteLine("The number of columns does not equal to no. of rows in source table!");
	else
	{
		DataRow dr = dstdt.NewRow();
		foreach(KeyValuePair<string, string> kvp in data)
		{
			dr[kvp.Key] = kvp.Value;
		}
		dstdt.Rows.Add(dr);
	}
	dstdt.Dump();
}

// Define other methods and classes here
DataTable GetInitialData()
{
	DataTable dt = new DataTable();
	dt.Columns.AddRange(new DataColumn[]
		{
			new DataColumn("name", typeof(string)),
			new DataColumn("value", typeof(string))
		});
	dt.Rows.Add(new object[]{"n1", "v1"});
	dt.Rows.Add(new object[]{"n2", "v2"});
	dt.Rows.Add(new object[]{"n3", "v3"});

	return dt;
}



Примечание: если там будут не уникальные данные, у вас будут проблемы ;)


0x01AA

SQL, pivot? Я возьму адвоката. Мой 5-й :)

Maciej Los

Спасибо, Бруно.

csrss

Мацей, я поступил следующим образом:
публичный статический словарь&ЛТ;tkey1, словарь&ЛТ;tkey2,="" tvalue=""&ГТ;&ГТ; сводная&ЛТ;метод tkey1,="" tkey2,="" tvalue=""&ГТ;(этот интерфейс IEnumerable&ЛТ;метод&ГТ; источник, Функ&ЛТ;метод tkey1=""&ГТ; key1Selector, Функ&ЛТ;метод tkey2=""&ГТ; key2Selector, Функ&ЛТ;интерфейс IEnumerable&ЛТ;метод&ГТ;, TValue&ГТ; совокупный)
        {
            возвратный источник.Метод groupBy(key1Selector).Выберите(x => new
            {
                Х = х.Ключ,
                Y = x.GroupBy(key2Selector).Выбрать(
                z => Новый
                {
                    З = з.Ключ,
                    V = агрегат(z)
                }).ToDictionary(e => e.Z, o => o.V)
            }).ToDictionary(e => e.X, o => o.Y);
        }
Эту я взял из сети. Итак, после применения вышеизложенного, следующее, что я сделал, это:
.Оси(Х => У Х.Selector1, х =&ГТ; х.Selector2, (х) =&ГТ; х.Список())
.Выберите(х =&ГТ;
{
var obj = new ExpandoObject() as IDictionary<string, object="">;
obj.Add("Column1", x.Key); // обязательный известный столбец
по каждому элементу (ВАР вал в X.Значение)
{
// динамический столбец
параметр obj.Добавить(знач.Значение.Первый().Имяполя, Вэл.Ключ);
}
возврат obj;
})

Однако это не сортируемое решение, потому что динамические столбцы не существуют таким же образом, как известные столбцы в динамическом объекте, поэтому я просто не могу сортировать с помощью LINQ, of group и т. д.
Поэтому я решил придерживаться T-SQL и динамических запросов + хранимых процедур.

Рейтинг:
1

Gerry Schmitz

Не знаю, почему вам "нужно" использовать LINQ (вы могли бы использовать его для "некоторых" частей).

Создайте словарь "имя,значение" и "суммируйте" значения, добавляя и обновляя словарь.

Во время "отчета" выведите "ключи" в виде заголовков, а "значения" - в виде значений столбцов.

(С LINQ вы группируете по имени с суммой по значению, а затем foreach 2 раза для печати, предполагая, что теперь он заказан)

Для "отчета" / печати замените массив, строку данных и т. д. на основе контекста.


csrss

Числовых данных нет - все строки и столбцы состоят из строковых значений. Нет, я не могу сделать это так, как вы говорите - сводная таблица применяется к большему запросу, поэтому возвращается результирующая таблица, которая имеет все возможности сортировки и фильтрации данных.

Gerry Schmitz

Это работает для "строк", предполагая, что они уникальны. Если строки не уникальны, то поворот не будет работать. Остальная часть вашего "разума" не имеет смысла.

csrss

Видите ли, я уже пробовал такое решение, как ваше, но, к сожалению, оно не работает.