Click here to Skip to main content
15,890,741 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 ;)
 
Share this answer
 
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.
 
Share this answer
 
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.
[no name] 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