Click here to Skip to main content
15,302,859 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hey everyone. I have such a table:
------------
name | value
------------
n1   | v1
n2   | v2
n3   | v3
------------

What is needed to be done is this:
------------
n1 | n2 | n3
------------
v1 | v2 | v3
------------

The thing is, table is a real life MSSQL table sitting in a database. Currently I am pivoting it using T-SQL Pivot, but need to do it with LINQ. Apart from that, new table have to be sortable as a regular table.
So, is that even possible? If it is - is there anyone, who knows how to do it? BTW, everything is dynamic here, and dynamic sql is used for T-SQL, columns are dynamic, etc.

What I have tried:

I've read probably everything on the net how to pivot tables, but nothing worked so far.
Posted
Updated 8-Mar-20 10:52am
v3
Comments
Maciej Los 7-Mar-20 14:51pm
   
There's no data on which data can be pivoted (group by).
:(

Take a look at below example (created in LinqPad):

C#
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;
}



Note: If there would be non-unique data, you'll be in trouble ;)
   
Comments
[no name] 8-Mar-20 17:06pm
   
SQL, pivot? I will take the attorney. My 5 :)
Maciej Los 8-Mar-20 17:18pm
   
Thank you, Bruno.
csrss 8-Mar-20 17:18pm
   
Maciej, I did the following way:
public static Dictionary<tkey1, dictionary<tkey2,="" tvalue="">> Pivot<tsource, tkey1,="" tkey2,="" tvalue="">(this IEnumerable<tsource> source, Func<tsource, tkey1=""> key1Selector, Func<tsource, tkey2=""> key2Selector, Func<ienumerable<tsource>, TValue> aggregate)
        {
            return source.GroupBy(key1Selector).Select(x => new
            {
                X = x.Key,
                Y = x.GroupBy(key2Selector).Select(
                z => new
                {
                    Z = z.Key,
                    V = aggregate(z)
                }).ToDictionary(e => e.Z, o => o.V)
            }).ToDictionary(e => e.X, o => o.Y);
        }
This one I took from the net. So after applying the above, next thing I did is:
.Pivot(x => x.Selector1, x => x.Selector2, (x) => x.ToList())
.Select(x =>
{
var obj = new ExpandoObject() as IDictionary<string, object="">;
obj.Add("Column1", x.Key); // mandatory known column
foreach (var val in x.Value)
{
// dynamic columns
obj.Add(val.Value.First().FieldName, val.Key);
}
return obj;
})

However, this is not sortable solution, because dynamic columns do not exist in same manner as known columns in dynamic object, so I just cannot sort with LINQ, of group, etcetera.
So I decided to stick with T-SQL and dynamic queries + stored procedure.
Don't know why you "need" to use LINQ (you could use it for "some" parts).

Create a <name,value> dictionary and "sum" the values by adding to and updating the dictionary.

At "report" time, print the "keys" as headings, and the "values" as column values.

(With LINQ, you groupby on name with a sum on value, then foreach 2 times for printing, assuming its now ordered)

For "report" / printing substitute array, data row, etc. based on context.
   
v2
Comments
csrss 7-Mar-20 15:30pm
   
There is no numeric data - all rows and columns consist of string values. No, I cannot do it like you say - pivoted table is applied to a bigger query so the result table is returned which has all possibilities of sorting and filtering data data.
Gerry Schmitz 7-Mar-20 15:35pm
   
It works for "strings", assuming they're unique. If the strings are NOT unique, then PIVOTING WON'T WORK. The rest of your "reason" makes no sense.
csrss 7-Mar-20 15:39pm
   
You see, I have already tried such solution as yours, but unfortunately it does not work.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900