-1

I have several tables (the exact number is not known when the program is build) looking like this (the number of rows and columns may differ from table to table):

enter image description here

The source data is stored in a data set. Now I want to generate a new table where all data of all ids is stored (the picture shows only the result for id 10 and 20 but the target table should contain the data for all ids):

enter image description here

The equivalent SQLite statement for that looks like this:

SELECT * FROM Dataset 
JOIN Datensatz2 ON (Dataset.ID=Datensatz2.ID)
JOIN Datensatz3 ON (Datensatz3.ID=Dataset.ID)
JOIN Datensatz4 ON (Datensatz4.ID=Dataset.ID)
WHERE Dataset.Id=10
UNION
SELECT * FROM Dataset 
JOIN Datensatz2 ON (Dataset.ID=Datensatz2.ID)
JOIN Datensatz3 ON (Datensatz3.ID=Dataset.ID)
JOIN Datensatz4 ON (Datensatz4.ID=Dataset.ID)
WHERE Dataset.Id=20
...

The double id columns will be removed afterwards so don´t worry about that. The questions is now how to convert it as a dynamic LINQ query?

xCHAN
  • 118
  • 15
derchrome
  • 85
  • 1
  • 1
  • 7
  • are you try something? – Grundy Aug 28 '15 at 06:22
  • What I have done is to select/join the data 'static' for a fixed amount of tables. But as I don´t know how many tables/ids there will be I have no idea how to generate a dynamic linq query. – derchrome Aug 28 '15 at 06:30
  • you should provide your code also – Grundy Aug 28 '15 at 07:03
  • 1
    You haven't mentioned that they are stored in a `DataSet` which they are according to [your previous question](http://stackoverflow.com/questions/32248072/c-sharp-dynamic-linq-query-at-runtime-on-datset). So currently people don't even know if this is a sql or C#/VB.NET question. It's also not clear why your sql filters by static IDs. – Tim Schmelter Aug 28 '15 at 07:19
  • What should happen with ID-rows that appear more than once in the same/different table, what should happen with ID rows which don't appear in all tables? What is the expected result at all? – Tim Schmelter Aug 28 '15 at 07:28
  • The whole thing is programmed in C# - Thanks Tim for that advice. The ID-rows that appear more than once are removed from the result afterwards. If an ID does not appear in one table the fields have to be empty (but that should not happen). To make it clearer: – derchrome Aug 28 '15 at 07:42
  • The whole dataset contains several products. Every product has a unique ID. Every product has several different parts/properties (they are represented by the different tables). – derchrome Aug 28 '15 at 07:45

2 Answers2

1

There are plenty of open question but maybe this helps to solve it. Since the tables are already stored in a DataSet you could use Linq-To-DataSet and Enumerable.GroupBy to group by ID:

var idTables = ds.Tables.Cast<DataTable>().Where(t => t.Columns.Contains("Id"));
if(!idTables.Any()){ MessageBox.Show("No id-tables"); return; }

var idRowGroups = idTables.SelectMany(t => t.AsEnumerable())
    .GroupBy(row => row.Field<int>("Id"))
    .Select(grp => new { ID = grp.Key, Rows = grp });

foreach(var idGroup in idRowGroups)
{
  Console.WriteLine("ID:{0} Rows:{1}"
      , idGroup.ID
      , String.Join(" | ", idGroup.Rows.Select(row => String.Join(",", row.ItemArray))));
}

Sample data:

var ds = new DataSet();
DataTable t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data", typeof(int));
t1.Rows.Add(1, 1);
t1.Rows.Add(2, 10);
t1.Rows.Add(3, 100);
t1.Rows.Add(4, 1000);
ds.Tables.Add(t1);
t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data", typeof(int));
t1.Rows.Add(4, 5);
t1.Rows.Add(5, 50);
t1.Rows.Add(7, 500);
t1.Rows.Add(3, 5997);
ds.Tables.Add(t1);
t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data1", typeof(int));
t1.Columns.Add("Data2", typeof(int));
t1.Rows.Add(1, 5, 0);
t1.Rows.Add(3, 7, 1);
t1.Rows.Add(5, 9, 11);
t1.Rows.Add(7, 11, 222);
ds.Tables.Add(t1);

Output:

ID:1 Rows:1,1 | 1,5,0
ID:2 Rows:2,10
ID:3 Rows:3,100 | 3,5997 | 3,7,1
ID:4 Rows:4,1000 | 4,5
ID:5 Rows:5,50 | 5,9,11
ID:7 Rows:7,500 | 7,11,222
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • i not sure, but seems something wrong with `String.Join(", ", String.Join("|", `, do you want `String.Join(", ", idGroup.Rows.Select(row => String.Join("|",row.ItemArray))))`? – Grundy Aug 28 '15 at 07:42
  • almost :-) `idGroup.Rows.Select` return `IEnumerable` you do `string.Join(" ")` and get `string` , but you again try do `String.Join(", ",` so i think `String.Join(", "` or `string.Join(" ",` should go away :-) – Grundy Aug 28 '15 at 07:46
  • Thank you Tim und Grundy! But that´s not what I need. Please see also my comments above and my first post (e.g. line 1-4 in the second picture are the possible combinations for ID 10). The result should be a datatable/list/collection where all possible combinations for all the products are listed. All the data for one product in one row. Depending the the possible product properties it could be only one row or many rows. – derchrome Aug 28 '15 at 08:12
  • I finally made it with your help @TimSchmelter :-) I did a combination of both o your answers (the one from yesterday and the one from today) but I am not really happy with that. I will share my solution as an answer but I think it is far too complacted :-). But maybe someone could help me improve it... – derchrome Aug 28 '15 at 09:38
0

Ok, I finally made it but it seems to be much too complicated. If someone is able to help me improve the solution he is very welcome.

DataSet dsResult = new DataSet();
        var idTables = ds.Tables.Cast<DataTable>().Where(t => t.Columns.Contains("ID"));
        if (!idTables.Any()) { MessageBox.Show("No id-tables"); return; }

        var idRowGroups = idTables.SelectMany(t => t.AsEnumerable())
            .GroupBy(row => row.Field<Int64>("ID"))
            .Select(grp => new { ID = grp.Key, Rows = grp });

        foreach (var idGroup in idRowGroups)
        {
            var liste = idGroup.Rows.ToList();
            for (int i = 0; i < liste.Count; i++)
            {
                if (!dsResult.Tables.Contains(liste[i].Table.TableName))
                {
                    dsResult.Tables.Add(liste[i].Table.TableName);
                    foreach (DataColumn dtCol in liste[i].Table.Columns)
                    {
                        if (dsResult.Tables[liste[i].Table.TableName].Columns.Contains("ID"))
                            dsResult.Tables[liste[i].Table.TableName].Columns.Add(dtCol.ColumnName+i.ToString());
                        else
                        {
                            dsResult.Tables[liste[i].Table.TableName].Columns.Add(dtCol.ColumnName);
                        }
                        dsResult.Tables[liste[i].Table.TableName].Columns[dtCol.ColumnName].DataType = dtCol.DataType;
                    }
                 }
                DataRow dRow = dsResult.Tables[liste[i].Table.TableName].NewRow();
                dRow.ItemArray = liste[i].ItemArray;
                dsResult.Tables[liste[i].Table.TableName].Rows.Add(dRow);
            }

            IEnumerable<IEnumerable<DataRow>> allTablesRows = dsResult.Tables.Cast<DataTable>()
            .Select(table => table.AsEnumerable())
            .CartesianProduct();

            int k = 0;

            foreach (var rows in allTablesRows)
            {
                DataRow zRow = dsErgebnis.Tables[2].NewRow();
                foreach (DataRow dRow in rows)
                {
                    for (int i = 0; i < dRow.ItemArray.Length; i++)
                    {
                        zRow[k] = dRow.ItemArray[i];
                        k++;
                    }
                }
                k = 0;
                dsErgebnis.Tables[2].Rows.Add(zRow);
            }
            dsResult.Clear();
       }

First I filter the content by ID.

Then I put the result in a new tables (all rows with the ID 10 I found in 'Datasatz2' in dataset 'ds' for example I put to a new table 'Datasatz2' in the dataset 'dsResult').

At least I build the cartesian product of all tables and store it in dtaset dsErgebnis.

The result is what I expect but as mentioned before I am not satisfied with the solution.

derchrome
  • 85
  • 1
  • 1
  • 7