Tag die Damen und Herren,
ich hoffe mir kann jemand helfen der sich gut mit LINQ auskennt....
Ich habe eine Datatable und diese möchte ich sortieren anhand von mehreren Spalten UND einer Datumspalte. Das wäre jetzt nicht das Problem, aber die Datumspalte muss bei jeder anderen Spalte mit abgefragt werden.
Eine Tabelle hat mehrere Spalten und eine Spalte mit Datum...
Jetzt müssen immer Gruppierungen erstellt werden
diese Gruppierungen müssen dann nach Datum sortiert werden.
SP1 - komplett A kommt vor B weil A mit kleinstem Datum beginnt... also ALLE A nacheinander, egal ob ein B dann zwischen den A liegt...
SP2 - komplett C vor D weil kleinstes Datum C kleiner als kleinstes Daum von D , egal ob ein D dann zwischen den C liegt...
SP3 ...... usw....
SP1 SP2 SP3 SP4 DAT1
A C .. .. 1.1.2000
A C .. .. 1.1.2004
A C .. .. 1.1.2008
A D .. .. 1.1.2006
B C .. .. 1.1.2002
B D .. .. 1.1.2006
B D .. .. 1.1.2008
Ich hoffe das ist verständlich....
ich bekomme das nicht mit dem Datum hin, also das binden an alle Spalten mit dem Datum
DataTable tmpSortTbl = tmpTbl.AsEnumerable()
.GroupBy(M_A => new { MA = M_A.Field<string>("SP1")})
.OrderBy(f => f.Key.MA)
.SelectMany(a2 => a2
.GroupBy(S_T => new { ST = S_T.Field<string>("SP2") })
.OrderBy(f => f.Key.ST)
.SelectMany(a3 => a3
.GroupBy(T_C => new { TC = T_C.Field<string>("SP3")})
.OrderBy(f => f.Key.TC)
.SelectMany(a4 => a4
.GroupBy(A_R => new { AR = A_R.Field<string>("SP4") })
.OrderBy(f => f.Key.AR)
.SelectMany(a6 => a6
.GroupBy(E_S => new { ES = E_S.Field<string>("SP5") })
.OrderBy(f => f.Key.ES)
.SelectMany(a8 => a8
)
)
)
)
)
.CopyToDataTable();
return tmpSortTbl;
Fettes merci
Hi ich sehe jetzt keine Möglichkeit wie du die Abfrage, direkt mit Linq umsetzen kannst. (Vieleicht hast du ja Glück und jemand anderes hat eine Idee).
Mein Ansatz wäre, die Listen in passende Teillisten zu zerlegen. Also erst mal Teilliste die nur als SP1 = A enthalt, daraus wider Teillisten bilden, die nur SP2 = C enthalten u.s.w bis SP4. Und dann würde ich hingehen und die Liste Rückwerts wieder zusammen zu setzen. Also SP4 passend nach Datum sortiert und dann SP2 usw.
Sollte man mal gelesen haben:
Hmmm die frage die sich mir jetzt stellt, versteht man mich nicht oder ist das in LINQ nicht möglich ?
var values = new []
{
new { SP1 = "A", SP2 = "C", Date = new DateTime(2000, 1, 1) },
new { SP1 = "A", SP2 = "C", Date = new DateTime(2004, 1, 1) },
new { SP1 = "A", SP2 = "C", Date = new DateTime(2008, 1, 1) },
new { SP1 = "A", SP2 = "D", Date = new DateTime(2006, 1, 1) },
new { SP1 = "B", SP2 = "C", Date = new DateTime(2002, 1, 1) },
new { SP1 = "B", SP2 = "D", Date = new DateTime(2006, 1, 1) },
new { SP1 = "B", SP2 = "D", Date = new DateTime(2008, 1, 1) }
};
values
.OrderBy(item => item.SP1)
.ThenBy(item => item.SP2)
.ThenBy(item => item.Date)
.ToList()
.ForEach(item => Console.WriteLine("{0} {1} {2}", item.SP1, item.SP2, item.Date.ToString("dd.MM.yyyy")));
Ist die ThenBy
-Methode das was du suchst?
Danke erstmal für die Antwort,
Ich glaube aber nicht.
Jeder Spalte (außer der Datumspalte) muss mit der Datumsspalte sortiert werden.
Also erst SP1 nach Datum - innerhalb davon SP2 mit Datum und innerhalb davon SP3 mit Datum....
Es kann sein das C aus SP2 ind SP1 A und B vorkommt....
Hi BeZi,
Also erst SP1 nach Datum - innerhalb davon SP2 mit Datum und innerhalb davon SP3 mit Datum....
Ist das nicht genau das, was Landos Lösung macht? Wenn nicht, mußt du ein bißchen konkreter werden, was noch nicht richtig funktioniert.
Christian
Weeks of programming can save you hours of planning
Wenn in SP1 das kleinste Datum von B kleiner ist als alle von A, dann sollen erst B's kommen und dann erst alle A's. Und das gleiche bei den Anderen Spalten.
(Hat BeZi aber auch so geschrieben, das Beispiel ist nur missverständlich. Das Ergebiss liefert Landos Abfrage.)
Sollte man mal gelesen haben:
Ich habe das Beispiel nun getestet und muss leider sagen das es so nicht funktioniert.
Von jeder Spalte muss es einen Rückschluss auf das kleinste Datum geben.
Bei mir wird nur jede Spalte alphabetisch sortiert ...
Ich weiss es lässt sich schwierig ausdrücken....
Das witzige ist das die eingabetabelle von Lando eigentlich schon das Ergebnis wiederspiegelt so wie es hinten rauspurzeln soll... Egal wie ich sie anlege
SP1 SP2 SP3 SP4 DAT1
A C .. .. 1.1.2000 <-----
A C .. .. 1.1.2004
A C .. .. 1.1.2008
A D .. .. 1.1.2006
B C .. .. 1.1.2002
B D .. .. 1.1.2006
B D .. .. 1.1.2008
ersten Eintrag geändert:
auf 2003 dann erwarte ich folgende Ausgabe
SP1 SP2 SP3 SP4 DAT1
B C .. .. 1.1.2002
B D .. .. 1.1.2006
B D .. .. 1.1.2008
A C .. .. 1.1.2003 <-----
A C .. .. 1.1.2004
A C .. .. 1.1.2008
A D .. .. 1.1.2006
Hi,
dann sollte Folgendes machen was du erwartest oder? (Habe 2016 noch ergänzt, da ich die Sortierung nach Datum allgemein noch mittesten wollte)
var values = new[]
{
new { SP1 = "A", SP2 = "C", Date = new DateTime(2003, 1, 1) },
new { SP1 = "A", SP2 = "C", Date = new DateTime(2016, 1, 1) },
new { SP1 = "A", SP2 = "C", Date = new DateTime(2004, 1, 1) },
new { SP1 = "A", SP2 = "C", Date = new DateTime(2008, 1, 1) },
new { SP1 = "A", SP2 = "D", Date = new DateTime(2006, 1, 1) },
new { SP1 = "B", SP2 = "C", Date = new DateTime(2002, 1, 1) },
new { SP1 = "B", SP2 = "D", Date = new DateTime(2006, 1, 1) },
new { SP1 = "B", SP2 = "D", Date = new DateTime(2008, 1, 1) }
};
values
.OrderBy(v => v.Date)
.ThenBy(v => v.SP1)
.ThenBy(v => v.SP2)
.GroupBy(v => v.SP1)
.OrderBy(g => g.Select(e => e.Date).Min())
.ToList()
.ForEach
(
grouping =>
grouping
.ToList()
.ForEach(item => Console.WriteLine("{0} {1} {2}", item.SP1, item.SP2, item.Date.ToString("dd.MM.yyyy")))
);
LG
Erstmal merci Taipi88,
ich habe eine Datatable und diese muss dann später nach der Sortierung wieder in eine Datatable, also am schluss ".CopyToDataTable();"
ich bekomme das so nicht hin mit foreach, da Foreach keinen Rückgabewert hat.
Wenn ich es durchlaufen lasse ist es auch so das er erst nach datum sortiert und dann nach SP1 ich will aber alle Werte innerhalb SP1 zusammen gesetzt und dann sortiert nach den Blöcken in SP1
Hi,
ja - er sortiert in der Tat zuerst nach Datum - allerdings nur um das später nicht für jeden einzelne Gruppe tun zu müssen - denke so wie folgt sollte es eher deinem Sinn entsprechen:
public static class Extensions
{
public static IEnumerable<T> Unwind<T>(this IEnumerable<IEnumerable<T>> list)
{
foreach (var l in list)
foreach (var e in l)
yield return e;
}
}
static void T2()
{
var values = new[]
{
new { SP1 = "A", SP2 = "C", Date = new DateTime(2003, 1, 1) },
new { SP1 = "A", SP2 = "C", Date = new DateTime(2016, 1, 1) },
new { SP1 = "A", SP2 = "C", Date = new DateTime(2004, 1, 1) },
new { SP1 = "A", SP2 = "C", Date = new DateTime(2008, 1, 1) },
new { SP1 = "A", SP2 = "D", Date = new DateTime(2006, 1, 1) },
new { SP1 = "B", SP2 = "C", Date = new DateTime(2002, 1, 1) },
new { SP1 = "B", SP2 = "D", Date = new DateTime(2006, 1, 1) },
new { SP1 = "B", SP2 = "D", Date = new DateTime(2008, 1, 1) }
};
values
.OrderBy(v => v.Date)
.GroupBy(v => v.SP1)
.Select(g => g
.GroupBy(v => v.SP2)
.OrderBy(g2 => g2.Select(e2 => e2.Date).Min())
.Unwind())
.OrderBy(g => g.Select(e => e.Date).Min())
.Unwind()
.ToList()
.ForEach(item => Console.WriteLine("{0} {1} {2}", item.SP1, item.SP2, item.Date.ToString("dd.MM.yyyy")));
}
Für die von mir notierten Eingangswerte - ergibt das folgende Ausgabe:
B C 01.01.2002
B D 01.01.2006
B D 01.01.2008
A C 01.01.2003
A C 01.01.2004
A C 01.01.2008
A C 01.01.2016
A D 01.01.2006
Oder habe ich jetzt noch was falsch verstanden? Wie genau hättest du denn die Ausgabe anders?
LG
Also irgendwie bekomme ich es nicht hin, ich habe folgendes:
DataTable tmpSortTbl = tmpTbl.AsEnumerable()
.GroupBy(A_R => new { ES = A_R.Field<string>("SP1") })
.OrderBy(f => f.Key.ES).ToList()
.SelectMany( a1=>a1
.GroupBy(A_R => new { AR = A_R.Field<string>("SP2") })
.OrderBy(f => f.Key.AR)
.SelectMany(a2 => a2
.GroupBy(T_C => new { TC = T_C.Field<string>("SP3").Split(' ')[1] })
.OrderBy(f => f.Key.TC)
.SelectMany(a3 => a3
.GroupBy(T_C => new { TC = T_C.Field<string>("SP4") })
.OrderBy(f => f.Key.TC)
.SelectMany(a4 => a4
.GroupBy(M_A => new { MA = M_A.Field<string>("SP6") })
.OrderByDescending(f => f.Key.MA)
.SelectMany(a6 => a6
.GroupBy(S_T => new { ST = S_T.Field<string>("SP7") })
.OrderBy(f => f.Key.ST)
.SelectMany(a7 => a7
.GroupBy(M_L => new { ML = M_L.Field<DateTime>("SP8")})
.OrderBy(f => f.Key.ML)
.SelectMany(a8 => a8)
)
)
)
)
)
)
).CopyToDataTable();
also mehrere Spalten. Alle diese werden nur nach dem Alphabet sortiert... Aber leider nicht nach datum ? Ich weiss auch leider nicht wie ich dieses Datum dort hineinbekomme.....
Ich sehe den Wald wohl vor lauter Bäumen nicht....
ARGGGGHHHHHHHH - HELP 🤔
Hast du meinen letzten Code überhaupt probiert?
Was du da treibst ist jeweils sortiert gruppieren - beginnend mit SP1.
Im Endeffekt nichts anderes wie (Pseudo-Code)
.OrderBy(SP1)
.ThenBy(SP2)
...
.ThenBy(SP8)
Nur deutlich umständlicher. So wie ich dich verstanden hatte - wolltest du jedoch gruppiert sortieren, wobei die Reihenfolge der jeweiligen Gruppen anhand des kleinsten Datums der Gruppe ermittelt wird. Das kleinste Datum verwendest du allerdings nicht mal irgendwo.
LG
Edit:
Mal auf dein Vorhaben zum durchtesten - aber hübsch ist das schon lange nicht mehr^^
static DataTable SortTable2(DataTable table)
{
return table.AsEnumerable()
.OrderBy(v => v["SP8"])
.GroupBy(v => v["SP1"])
.Select(g => g
.GroupBy(v => v["SP2"])
.OrderBy(g2 => g2.Select(e2 => e2["SP8"]).Min())
.Select(g3 => g3
.GroupBy(v2 => v2["SP3"].ToString().Split(' ')[1])
.OrderBy(g4 => g4.Select(e3 => e3["SP8"]).Min())
.Select(g4 => g4
.GroupBy(v2 => v2["SP4"])
.OrderBy(g5 => g5.Select(e3 => e3["SP8"]).Min())
.Select(g5 => g5
.GroupBy(v2 => v2["SP5"])
.OrderBy(g6 => g6.Select(e3 => e3["SP8"]).Min())
.Select(g7 => g7
.GroupBy(v2 => v2["SP6"])
.OrderBy(g8 => g8.Select(e3 => e3["SP8"]).Min())
.Select(g8 => g8
.GroupBy(v2 => v2["SP6"])
.OrderBy(g9 => g9.Select(e3 => e3["SP8"]).Min())
.SelectMany(r1 => r1))
.SelectMany(r1 => r1))
.SelectMany(r1 => r1))
.SelectMany(r1 => r1))
.SelectMany(r1 => r1))
.SelectMany(r1 => r1))
.OrderBy(g => g.Select(e => e["SP8"]).Min())
.SelectMany(r1 => r1)
.CopyToDataTable();
}
Sali @Taipi88 und merci...
Habe es getestet und es funktioniert doch, hatte einen fehler beim übernehmen...
Wie bekomme ich es hin noch weitere Spalten nach dem gleichen Schema hinzuzufügen. Es ist mir nicht ganz klar....
und danke nochmals.... Echt top
WOW, OPS..... Übersehen, sorry
und fettes merci nochmals
megacool... das nenn ich Hilfe