Build one datatable out of two with certain conditions - c#

Firstly I need to get all the data from ODBC (this is working already).
Then comes the most complicated part that I am not sure yet how it can be done.
There are two tables of data in ODBC. I am merging them with my current code and filtering them with certain parameters.
Table 1 in database:
NRO NAME NAMEA NAMEB ADDRESS POSTA POSTN POSTADR COMPANYN COUNTRY ID ACTIVE
123 Fiat Punto 500 J5 K4 O3 P4 O2 JT 1 1
133 Opel Meriva FTG J5 K4 O3 P4 O2 JO 3 1
153 MB E200 C25 JN KI OP PY OR JD 5 1
183 BMW E64 SE0 JR KE OT PG OL J8 9 1
103 Audi S6 700 JP KU OU PN OH J6 11 1
Table 2 in database:
NRO NAME NAMEA NAMEB ADDRESS POSTA POSTN POSTADR COMPANYN COUNTRY ID ACTIVE
423 Fiat Punto 500 J5 K4 O3 P4 O2 JT 1 1
463 BMW E64 SE0 JR KE OT PG OL J8 9 1
Merged dataTable look like this:
NRO NAME NAMEA NAMEB ADDRESS POSTA POSTN POSTADR COMPANYN COUNTRY ID ACTIVE
423 Fiat Punto 500 J5 K4 O3 P4 O2 JT 1 1
463 BMW E64 SE0 JR KE OT PG OL J8 9 1
123 Fiat Punto 500 J5 K4 O3 P4 O2 JT 1 1
133 Opel Meriva FTG J5 K4 O3 P4 O2 JO 3 1
153 MB E200 C25 JN KI OP PY OR JD 5 1
183 BMW E64 SE0 JR KE OT PG OL J8 9 1
103 Audi S6 700 JP KU OU PN OH J6 11 1
However merged output dataTable should look like this (to have a possibility to work with it further):
NRO NRO1 NAME NAMEA NAMEB ADDRESS POSTA POSTN POSTADR COMPANYN COUNTRY ID ACTIVE
123 423 Fiat Punto 500 J5 K4 O3 P4 O2 JT 1 1
133 Opel Meriva FTG J5 K4 O3 P4 O2 JO 3 1
153 MB E200 C25 JN KI OP PY OR JD 5 1
183 463 BMW E64 SE0 JR KE OT PG OL J8 9 1
103 Audi S6 700 JP KU OU PN OH J6 11 1
Find duplicates in NAME. Leave only one of them, assign a number from Table 1 to NRO from Table 2 to NRO1. Table 1 numbers should be in NRO, Table 2 numbers should be in NRO1.
After connecting to ODBC I am filling one table with data from Table 1
DataTable dataTable = new DataTable("COMPANY");
using (OdbcConnection dbConnectionSE = new OdbcConnection(connectionStringSE))
{
dbConnectionSE.Open();
OdbcDataAdapter dadapterSE = new OdbcDataAdapter();
dadapterSE.SelectCommand = new OdbcCommand(queryStringSE, dbConnectionSE);
dadapterSE.Fill(dataTable);
}
then I am getting data from another Table 2 and merging them by:
using (OdbcConnection dbConnectionFI = new OdbcConnection(connectionStringFI))
{
dbConnectionFI.Open();
OdbcDataAdapter dadapterFI = new OdbcDataAdapter();
dadapterFI.SelectCommand = new OdbcCommand(queryStringFI, dbConnectionFI);
var newTable = new DataTable("COMPANY");
dadapterFI.Fill(newTable);
dataTable.Merge(newTable);
}
After that I am performing filtering (I need to have rows only starting with 4 and 1 in NRO, there are also rows with other starting number):
DataTable results = dataTable.Select("ACTIVE = '1' AND (NRO Like '1%' OR NRO Like '4%')").CopyToDataTable();
Then I am adding one more Column for NRO1 (this is also adding zeros (0) I don't need them in Column NRO1):
results.Columns.Add("NRO1", typeof(int)).SetOrdinal(1);
foreach (DataRow row in results.Rows)
{
//need to set value to NewColumn column
row["NRO1"] = 0; // or set it to some other value
}
I can catch duplicates with this code
var duplicates = results.AsEnumerable().GroupBy(r => r[2]).Where(gr => gr.Count() > 1);
but how to perform the rest? This should be performed by a loop with building a new table? How I can perform joining and removing duplicates to dataTable?

You could replace the merge() call with a custom method, which does the merging and filtering at the same time. See the example below. I think this is a better approach than first merging (introducing duplicate rows in the result table) and then filtering (i.e. removing the duplicate rows).
Here, it is assumed that the parameters all have the same format. The tTemp table is used as a temporary storage for the contents of table t2 but with the extra column. This allows importing the rows in the result table.
Maybe there is a more elegant solution, but this should work as intended. Please note that I have left out your additional requirement regarding the allowed values for NRO, which I am sure you can add easily.
static void merge_it(DataTable t1, DataTable t2, DataTable tResult, DataTable tTemp)
{
tResult.Merge(t1);
tResult.Columns.Add("NRO1", typeof(int));
tTemp.Merge(t2);
tTemp.Columns.Add("NRO1", typeof(int));
foreach (DataRow row in tTemp.Rows)
{
string name1 = row.Field<string>("NAME");
string name2 = row.Field<string>("NAMEA");
DataRow[] matches = tResult.Select($"NAME = '{name1}' AND NAMEA = '{name2}'");
if (matches.Length > 0)
{
matches[0].SetField<int>("NRO1", row.Field<int>("NRO"));
}
else
{
tResult.ImportRow(row);
}
}
foreach (DataRow row in tResult.Rows)
{
if (row["NRO1"] == DBNull.Value)
{
row["NRO1"] = 0;
}
}
}

Try this:
Include NRO1 field in both queries for Table1 and Table2
Set default value 0 of NRO1 for Table1 (modify queryStringSE)
e.g.:SELECT NRO,0 AS NRO1, NAME,NAMEA,NAMEB, ... FROM TABLE1
Set default value 0 of NRO for Table2 (modify queryStringFI)
e.g.:SELECT 0 AS NRO,NRO AS NRO1,NAME,NAMEA,NAMEB,...... FROM TABLE2
Table1 will look like:
NRO NRO1 NAME NAMEA NAMEB ADDRESS POSTA POSTN POSTADR COMPANYN COUNTRY ID ACTIVE
123 0 Fiat Punto 500 J5 K4 O3 P4 O2 JT 1 1
133 0 Opel Meriva FTG J5 K4 O3 P4 O2 JO 3 1
Table2 will look like:
NRO NRO1 NAME NAMEA NAMEB ADDRESS POSTA POSTN POSTADR COMPANYN COUNTRY ID ACTIVE
0 423 Fiat Punto 500 J5 K4 O3 P4 O2 JT 1 1
0 463 BMW E64 SE0 JR KE OT PG OL J8 9 1
Merge tables as you are already doing
Add following lines of code:
var carGroups = dataTable.AsEnumerable().GroupBy(row => new
{
Name = row.Field<string>("Name"),
NameA = row.Field<string>("NAMEA"),
NameB = row.Field<string>("NAMEB")
//Other fields.....
});
DataTable result = dataTable.Clone();
foreach(var grp in carGroups)
result.Rows.Add(grp.Sum(r1 => r1.Field<int>("NRO")), grp.Sum(r2 => r2.Field<int>("NRO1")), grp.Key.Name, grp.Key.NameA, grp.Key.NameB);
Check DataTable "result" for desired values

you can keep same column name in both table if they denote same type of entity
then see this code
private static void DemonstrateMergeTable()
{
DataTable table1 = new DataTable("Items");
// Add columns
DataColumn idColumn = new DataColumn("id", typeof(System.Int32));
DataColumn itemColumn = new DataColumn("item", typeof(System.Int32));
table1.Columns.Add(idColumn);
table1.Columns.Add(itemColumn);
// Set the primary key column.
table1.PrimaryKey = new DataColumn[] { idColumn };
// Add RowChanged event handler for the table.
table1.RowChanged += new
System.Data.DataRowChangeEventHandler(Row_Changed);
// Add ten rows.
DataRow row;
for (int i = 0; i <= 9; i++)
{
row = table1.NewRow();
row["id"] = i;
row["item"] = i;
table1.Rows.Add(row);
}
// Accept changes.
table1.AcceptChanges();
PrintValues(table1, "Original values");
// Create a second DataTable identical to the first.
DataTable table2 = table1.Clone();
// Add column to the second column, so that the
// schemas no longer match.
table2.Columns.Add("newColumn", typeof(System.String));
// Add three rows. Note that the id column can't be the
// same as existing rows in the original table.
row = table2.NewRow();
row["id"] = 14;
row["item"] = 774;
row["newColumn"] = "new column 1";
table2.Rows.Add(row);
row = table2.NewRow();
row["id"] = 12;
row["item"] = 555;
row["newColumn"] = "new column 2";
table2.Rows.Add(row);
row = table2.NewRow();
row["id"] = 13;
row["item"] = 665;
row["newColumn"] = "new column 3";
table2.Rows.Add(row);
// Merge table2 into the table1.
Console.WriteLine("Merging");
table1.Merge(table2, false, MissingSchemaAction.Add);
PrintValues(table1, "Merged With table1, schema added");
}
private static void Row_Changed(object sender,
DataRowChangeEventArgs e)
{
Console.WriteLine("Row changed {0}\t{1}", e.Action,
e.Row.ItemArray[0]);
}
private static void PrintValues(DataTable table, string label)
{
// Display the values in the supplied DataTable:
Console.WriteLine(label);
foreach (DataRow row in table.Rows)
{
foreach (DataColumn col in table.Columns)
{
Console.Write("\t " + row[col].ToString());
}
Console.WriteLine();
}
}

Related

Merge two datatables in C#?

I have two datatables ..
DataTable dtTemp= new DataTable();
dtTemp.Columns.AddRange(new[]
{
new DataColumn("segment_id", typeof(int)),
new DataColumn("seg_description")
});
DataTable dtTemp2 = new DataTable();
dtTemp2.Columns.Add("set_id",typeof(int));
Now lets have some rows into first table..
segment_id|seg_description
------ |---------------
1 | desc..
2 | desc2..
3 | desc3..
Now lets have some data into second table..
set_id
--------
1
--------
2
Now, I want marge this two tables to get below output
set_id | segment_id |seg_description
--------| ---------- | --------------
1 | 1 | desc..
1 | 2 | desc2..
1 | 3 | desc3..
2 | 1 | desc..
2 | 2 | desc2..
2 | 3 | desc3..
How can I do this?using Merge() can I achieve this?
So you want to "cross-join" the tables by building a cartesian product of all rows? Of course there is no builtin way, you can use this method:
public static DataTable CrossJoinTables(DataTable t1, DataTable t2)
{
if (t1 == null || t2 == null)
throw new ArgumentNullException("t1 or t2", "Both tables must not be null");
DataTable t3 = t1.Clone(); // first add columns from table1
foreach (DataColumn col in t2.Columns)
{
string newColumnName = col.ColumnName;
int colNum = 1;
while (t3.Columns.Contains(newColumnName))
{
newColumnName = string.Format("{0}_{1}", col.ColumnName, ++colNum);
}
t3.Columns.Add(newColumnName, col.DataType);
}
IEnumerable<object[]> crossJoin =
from r1 in t1.AsEnumerable()
from r2 in t2.AsEnumerable()
select r1.ItemArray.Concat(r2.ItemArray).ToArray();
foreach(object[] allFields in crossJoin)
{
t3.Rows.Add(allFields);
}
return t3;
}
Usage:
DataTable tblresult = CrossJoinTables(dtTemp2, dtTemp); // swapped order because you want columns from dtTemp2 first
To do this you need to use the CROSS JOIN operation.
Select * Table1 CROSS JOIN Table2
It literally gives you the product of the two tables : Every row in A joined to every row in B. if A has 100 rows and B has 100 rows, the Cross Join has 10,000 rows.
How about this:
var dt1 = dtTemp1.AsEnumerable();
var dt2 = dtTemp2.AsEnumerable();
var q = from x in dt1
from y in dt2
select new { set_id = (int)y["set_id"], segment_id = (int)x["segment_id"], seg_description = (string)x["seg_description"] };

Get DataTable Value from Adjacent Cell without ForEach loop?

I am working my way around this problem: Create multiple results from single row joining either 2 or 3 tables based off conditional of table1 results? and while I wish I could take Strawberry's advice, I can't, so I am trying now to do more in C# rather than through the DB, but also trying to be smart about how much CPU I utilize.
For scale, table1 may have 50,000 records which have those 20 codetype fields which have to be evaluated before they can be matched to table2, which has about 2,000 rows, or table3, which could have 200,000 rows. To avoid hammering the DB, I am going to store what is possible in memory, limit results by date as much as possible, but I want to avoid 2,000 foreach loops per 20 codetype matches.
To start off, I am getting the results I need from table2 and loading them into a C# DataTable stored as the variable named descriptionLookup:
id, description
13 Item 13 Description
15 Item 15 Description
17 Item 17 Description
18 Item 18 Description
21 Item 21 Description
28 Item 28 Description
45 Item 45 Description
And table3 as lookupTable:
id, table2id
1 15
33 17
21 28
doing a simple (not showing all surrounding code, just relevant):
var rawData = new DataTable();
using (OdbcCommand com = new OdbcCommand("SELECT id, description from table2", conn))
{
using (OdbcDataReader reader = com.ExecuteReader())
{
rawData.Load(reader);
conn.Close();
return rawData;
}
}
I then have that assigned to a variable that called the function. Now I have to deal with table1:
codeid1,codeid2,codeid3,...codeid20 ... codetype1,codetype2,codetype3,.....codetype20
18 13 1 33 0 0 1 1
13 21 45 0 0 1 0 0
Using a foreach row, I need to evaluate each codetype column for a 1 or a 0. When codetype=1 I need to grab the associated codeid, and then do a lookup from the data I am holding in memory as descriptionLookup to see what the table2id is that matches the id in lookuptable and then use that to lookup the description of the associated field in table2.
If codetype is 0, I just need to match codeid with the associated description field in table2.
I am looking at how to lay this out, and all I can think of is:
DataTable descriptionLookup= DB.ExecuteQuery("SELECT id, description from table2");
DataTable lookupTable= DB.ExecuteQuery("SELECT id, table2id from table3");
DataTable mainData= DB.ExecuteQuery("SELECT * from from table1");
foreach (var row in mainData)
{
var manDataId = row.GetColumn("id");
var subroutine = new Dictionary<string, string>();
for (var index = 1; index < 20; index++)
{
string description;
if (row.GetColumn("codetype" + index) == "1")
{
int idLookup = row.GetColumn(["codeid" +index]);
foreach (var row2 in lookupTable)
{
if (row3.GetColumn("id") == idLookup)
{
descriptionId = row3.GetColumn("table2id");
foreach (var row2 in descriptionLookup)
{
if (row.GetColumn("id") == descriptionId)
{
description = row2.GetColumn("description").ToString();
}
}
}
}
}elseif (row.GetColumn("codetype" + index) == "0")
{
descriptionId = row.GetColumn(["codeid" +index]);
foreach (var row2 in descriptionLookup)
{
if (row.GetColumn("id") == descriptionId)
{
description = row2.GetColumn("description").ToString();
}
}
}
subroutine.Add(manDataId.ToString(), description.ToString());
}
ArrayData.Add(subroutine);
}
I haven't tried running the above code, so there is probably a problem or two in there, but it gets the point across of looping through thousands of records using foreach (var row3 in idLookup). The alternative seems to be making a DB query, but that seems more intensive than just looping through what is in memory, but it seems like there is a better way that I am missing on how to get the id or table2id without using a foreach.
To make this the longest looking question in history :) Here is my SQL that I have so far:
SELECT table1.id, table1.field1, table1.field2,
table2.description, fee.amt as fee FROM table2
INNER JOIN table1
ON table2.id = table1.codeid1
OR table2.id = table1.codeid2
OR table2.id = table1.codeid3
OR table2.id = table1.codeid4
OR table2.id = table1.codeid5
OR table2.id = table1.codeid6
OR table2.id = table1.codeid7
OR table2.id = table1.codeid8
OR table2.id = table1.codeid9
OR table2.id = table1.codeid10
OR table2.id = table1.codeid11
OR table2.id = table1.codeid12
OR table2.id = table1.codeid13
OR table2.id = table1.codeid14
OR table2.id = table1.codeid15
OR table2.id = table1.codeid16
OR table2.id = table1.codeid17
OR table2.id = table1.codeid18
OR table2.id = table1.codeid19
OR table2.id = table1.codeid20
INNER JOIN fee ON table2.id = fee.id
WHERE table1.codetype1 = 0
AND table1.codetype2 = 0
AND table1.codetype3 = 0
AND table1.codetype4 = 0
AND table1.codetype5 = 0
AND table1.codetype6 = 0
AND table1.codetype7 = 0
AND table1.codetype8 = 0
AND table1.codetype9 = 0
AND table1.codetype10 = 0
AND table1.codetype11 = 0
AND table1.codetype12 = 0
AND table1.codetype13 = 0
AND table1.codetype14 = 0
AND table1.codetype15 = 0
AND table1.codetype16 = 0
AND table1.codetype17 = 0
AND table1.codetype18 = 0
AND table1.codetype19 = 0
AND table1.codetype20 = 0
This works great as long as there isn't any of the codetype that have a 1, otherwise that record will be skipped. There will likely not be a single row where all codeid / codetype are filled out, nor will there ever be a case where codetype will be 1 across the board to match the inverse of this query.

LINQ query for grouping a table based on the values from another table

I am trying write C# LINQ to join a table based on the values from a different table
For example, I have two tables Table1 and Table2 as below
Table1
Id Name Address StatusId SubStatusId Dubs
1 ABC XYZ 1 39 10
2 PQR XYZ 1 39 0
3 ME WWW 2 39 5
4 YOU XYZ 1 22 0
5 HE XYZ 2 22 5
6 SHE WWW 2 41 0
7 XAZ XYZ 1 39 10
Table2
Id StatusId SubStatusId Status SubStatus Type
1 1 39 Dispense Ready 1
2 1 39 Fill Ready 2
3 2 22 Ship Active 0
4 2 41 Del Pending 0
5 1 22 Verify Pending 0
6 2 39 Benefit None 0
Now, I am trying to join both tables with StatusId and SubstatusId Columns as follows
from p in context.Table1
join label in context.Table2 on new
{
p.StatusId,
p.SubStatusId,
I = p.Dubs== 0,
J = p.Dubs> 0
} equals
new
{
label.StatusId,
label.SubStatusId,
I = label.type== 1
J = label.type== 2
} into gj
from label in gj.DefaultIfEmpty()
The above code join two tables by four values properties but I would like to exclude I and J when type of the row in Table2 is zero no matters what value is in Dubs
Result looks like below
Status SubStatus
Fill Ready (1,39 Since Dubs>0 for which means should return row with type 2)
Dispense Ready (1,39 Since Dubs=0 for which means should return row with type 1)
Benefit None (2, 39 Since type=0, this should ignore Dubs)
Verify Pending (same as above)
Ship Active
Del Pending
Fill Ready (1,39 Since Dubs>0 for which means should return row with type 2)
I would keep the more complex predicates out of the join:
from p in context.Table1
join label in context.Table2 on new
{
p.StatusId,
p.SubStatusId,
} equals new
{
label.StatusId,
label.SubStatusId,
} into gj
from label in gj.DefaultIfEmpty()
where label.Type == 0
|| label.Type == (p.Dubs == 0 ? 1 : 2)
select ...
The join syntax seems easier to control inside of a Where.
The where doesn't match yours, but you should be able to build the complex clause based upon this more easily.
var aresult = from a in ta.AsEnumerable()
from b in tb.AsEnumerable()
.Where(b => a.Field<string>("StatusId") == b.Field<string>("StatusId")
&& a.Field<string>("SubStatusId") == b.Field<string>("SubStatusId"))
select new object[] { a.Field<string>("Name")
,b.Field<string>("Status")
,b.Field<string>("SubStatus")
};
Code to generate tables given ...
DataTable ta = new DataTable();
ta.Columns.Add("Id");
ta.Columns.Add("Name");
ta.Columns.Add("Address");
ta.Columns.Add("StatusId");
ta.Columns.Add("SubStatusId");
ta.Columns.Add("Dubs");
DataTable tb = new DataTable();
tb.Columns.Add("Id");
tb.Columns.Add("StatusId");
tb.Columns.Add("SubStatusId");
tb.Columns.Add("Status");
tb.Columns.Add("SubStatus");
tb.Columns.Add("Type");
string[] tas =
{
"1,ABC,XYZ,1,39,10"
,"2,PQR,XYZ,1,39,20"
,"3,ME,WWW,2,39,0"
,"4,YOU,XYZ,1,22,2"
,"5,HE,XYZ,2,22,5"
,"6,SHE,WWW,2,41,0"
};
string[] tbs =
{
"1,1,39,Dispense,Ready,1"
,"2,2,39,Fill,Ready,2"
,"3,2,22,Ship,Active,0"
,"4,2,41,Del,Pending,0"
,"5,1,22,Verify,Pending,0"
};
foreach (string t in tas)
{
string[] x = t.Split(',');
DataRow row = ta.NewRow();
for (int i = 0; i < x.Length; i++) row[i] = x[i];
ta.Rows.Add(row);
}
foreach (string t in tbs)
{
string[] x = t.Split(',');
DataRow row = tb.NewRow();
for (int i = 0; i < x.Length; i++) row[i] = x[i];
tb.Rows.Add(row);
}

How to loop and update SQL table summing any existing values

Please i need your help on this module part of my program. i have 2 tables, TableA which has "code,description,value" and TableB which has "code, values" example below :
TableA
code description value
-----------------------------
CD1 BOOKS
CD2 BREADS
CD3 PHONES
CD4 FISH
TableB
code value1 value2 value3 value4
--------------------------------------
cd1 12 21 10 21
cd2 9 10 10 11
cd3 19 11 29 13
cd4 10 12 22 12
the idea is to update TableA with the Values of TableB where TableA.code=TableB.code but if their are values in TableA then Update content of TableA Value field by adding the new values to the old value field where TableB.code = TableA.code. i have written the following code but it's only updating one row, below is my code :
DataTable dt = GetDatafromDatabase(); //===== returns a DataTable
string SQLT = "SELECT * FROM tbl_TempReport";
if (cn.State == ConnectionState.Closed) {cn.Open(); }
SqlCommand cmdT = new SqlCommand(SQLT, cn);
while (rt.Read())
{
// For each row, print the values of each column.
foreach (DataColumn column in dt.Columns)
{
foreach (DataRow row in dt.Rows)
{
colname = column.ColumnName.ToString();
string m_Code = rt["code"].ToString();
if (m_Code == colname) {
if (m_Code == colname && mValue > 0) { mValue += Convert.ToInt32(row[column].ToString()); } else { mValue = Convert.ToInt32(row[column].ToString()); }
//============ insert into tbl_TempReport to match the appropriate column
string SQLP = "UPDATE tbl_TempReport SET VALUEP = #VALUEP WHERE code = #code";
SqlCommand cmdp = new SqlCommand(SQLP, cn);
cmdp.Parameters.AddWithValue("#VALUEP", SqlDbType.Int).Value = mValue;
cmdp.Parameters.AddWithValue("#code", SqlDbType.NVarChar).Value = rt["code"].ToString();
cmdp.ExecuteNonQuery();
}
}
}
}
i need your help to achieve this. Thank you
If I understand the question, this can be done in a single update statement, without any loops:
UPDATE a
SET value = b.value1 + b.value2 + b.value3 + b.value4 + COALESCE(value, 0)
FROM TableA a
INNER JOIN TableB b ON(a.code = b.code)

How to concat a column value based on id

I have a table like this in C# from a dataset
COL1 COL2 COL3 COL4 COL5
1000 APPLE 50 92 TESTING
1000 APPLE 50 92 ALPHA
1000 APPLE 50 92 BETA
1000 APPLE 50 92 OMEGA
2000 ORANGE 60 90 DELTA
2000 ORANGE 60 90 TEST
2000 ORANGE 60 90 SLEEP
I need result like this
COL1 COL2 COL3 COL4 COL5
1000 APPLE 50 92 TESTINGAPHABETAOMEGA
2000 ORANGE 60 90 DELTASLEEPTEST
How to achieve this ?
I strucked after this line
var result = from row in dataTable.AsEnumerable()
group row by row.Field<int>("COL1") into grp
select new
{
COL1= grp.Key,
Count = grp.Count()
};
I dont think you can do that with LINQ, but heres a little subroutine that will work for you.
var _rowlist = table.AsEnumerable().OrderBy(x => x.Field<Int32>("COL1")).ThenBy(x => x.Field<string>("COL2")).ThenBy(x => x.Field<string>("COL3")).ThenBy(x => x.Field<string>("COL4")).ToList();
DataTable _newtable = table.Clone();
string oldrowid = "";
foreach (DataRow _indrow in _rowlist)
{
if (!oldrowid.Equals(_indrow["COL1"].ToString()))
{
oldrowid = _indrow["COL1"].ToString();
DataRow _newrow = _newtable.NewRow();
_newrow["COL1"] = _indrow["COL1"].ToString();
_newrow["COL2"] = _indrow["COL2"].ToString();
_newrow["COL3"] = _indrow["COL3"].ToString();
_newrow["COL4"] = _indrow["COL4"].ToString();
_newrow["COL5"] = _indrow["COL5"].ToString();
_newtable.Rows.Add(_newrow);
}
else
{
Int32 _id = Int32.Parse(_indrow["COL1"].ToString());
DataRow _row = _newtable.AsEnumerable().Where(a => a.Field<Int32>("COL1") == _id).SingleOrDefault();
int Index = _newtable.Rows.IndexOf(_row);
_row["COL5"] += "," + _indrow["COL5"].ToString();
}
}
//_newtable contains what you want
Try this:
var result =
from row in dataTable.AsEnumerable()
let COL1 = row.Field<int>("COL1")
let COL2 = row.Field<string>("COL2")
let COL3 = row.Field<int>("COL3")
let COL4 = row.Field<int>("COL4")
let COL5 = row.Field<string>("COL5")
group COL5 by new { COL1, COL2, COL3, COL4, } into grp
select new
{
COL1 = grp.Key.COL1,
COL2 = grp.Key.COL2,
COL3 = grp.Key.COL3,
COL4 = grp.Key.COL4,
COL5 = String.Join("", grp),
};
var result = from row in dt.AsEnumerable()
group row by row.Field<int>("COL1") into grp
let firstCols = grp.First()
let lastCells = string.Join("", grp.Select(x => x[4]).ToArray())
select new object[] { firstCols[0], firstCols[1], firstCols[2], firstCols[3], lastCells };
var dtResult = dt.Clone();
foreach (var item in result )
{
dtResult.Rows.Add(item);
}

Categories