Здравствуйте,
Имеется несколько таблиц одинаковой структуры (столбцы k0, k1, day и res).
Нужно объединить значения 2..N таблиц со одинаковыми значениями k0 и k1, т.е. получить таблицу вида:
k0_табл1 k1_табл1 day_табл1 res_табл1 day_табл2 res_табл2 ... day_таблN res_таблN
Очень не хочется писать метод для каждого N. Понимаю, что можно сделать в цикле, рекурентно. Тем более, что запрос join будет не самым трудным, но вот как написать к нему select с переменным числом параметров мне совсем не ясно.
Иными словами:
начало запроса
var q =
from dr1 in dt1.AsEnumerable() // к чему присоединяем
join dr2 in dt2.AsEnumerable() // что присоединяем
on new {
k0 = dr1["k0"],
k1 = dr1["k1"]}
equals new {
k0 = dr2["k0"],
k1 = dr2["k1"]}
А дальше селект с переменным числом полей типа
select new {
k0 = dr1["k0"],
k1 = dr1["k1"],
day_1 = dr1["day"], // типа первый день, который уже в dt1
res_1 = dr1["res"],
...
day_n = dr1["day_n"], // типа последний день, который уже в dt1
res_n = dr1["res_n"],
day_n+1 = dr2["day"], // из dt2
res_n+1 = dr2["res"],
}
Здравствуйте, abb269, Вы писали:
A>Имеется несколько таблиц одинаковой структуры (столбцы k0, k1, day и res). A>Нужно объединить значения 2..N таблиц со одинаковыми значениями k0 и k1, т.е. получить таблицу вида: A> k0_табл1 k1_табл1 day_табл1 res_табл1 day_табл2 res_табл2 ... day_таблN res_таблN
A>Очень не хочется писать метод для каждого N. Понимаю, что можно сделать в цикле, рекурентно. Тем более, что запрос join будет не самым трудным, но вот как написать к нему select с переменным числом параметров мне совсем не ясно.
Не совсем ясно, что потом с результатом делать. Допустим, получишь ты анонимный класс с переменным числом полей (через рефлекшен или экспрешены такое можно сотворить), а как его использовать потом?
Здравствуйте, abb269, Вы писали:
A>Здравствуйте, A>Имеется несколько таблиц одинаковой структуры (столбцы k0, k1, day и res). A>Нужно объединить значения 2..N таблиц со одинаковыми значениями k0 и k1, т.е. получить таблицу вида: A> k0_табл1 k1_табл1 day_табл1 res_табл1 day_табл2 res_табл2 ... day_таблN res_таблN A>Очень не хочется писать метод для каждого N. Понимаю, что можно сделать в цикле, рекурентно. Тем более, что запрос join будет не самым трудным, но вот как написать к нему select с переменным числом параметров мне совсем не ясно.
A>Заранее благодарю за оперативный ответ
IMHO сложно будет. Кода будет больше, че м если тупо функции наделать для каждого N.
Я имею в виду если делать через Expression.
Например есть dynamiclinq, но оно джойны не умеет.
// для тестаclass Row
{
public string k0 { get; set; }
public string k1 { get; set; }
public int day { get; set; }
public int res { get; set; }
}
const int N = 3;
static Row[][] tables =
{
new []
{
new Row {k0 = "0", k1 = "42", day = 10, res = 100},
new Row {k0 = "1", k1 = "43", day = 10, res = 100},
new Row {k0 = "2", k1 = "44", day = 10, res = 100},
},
new []
{
new Row {k0 = "0", k1 = "42", day = 20, res = 200},
new Row {k0 = "1", k1 = "43", day = 20, res = 200},
new Row {k0 = "3", k1 = "44", day = 20, res = 200},
},
new []
{
new Row {k0 = "0", k1 = "42", day = 30, res = 300},
new Row {k0 = "1", k1 = "43", day = 30, res = 300},
new Row {k0 = "4", k1 = "44", day = 30, res = 300},
}
};
static void Main(string[] args)
{
// собственно код
IQueryable query = tables[0].AsQueryable().Select("new(k0, k1, day as day0, res as res0)");
foreach (var i in Enumerable.Range(1, N - 1))
{
var fields = string.Join("", Enumerable.Range(0, i).Select(n => $"inner.day{n}, inner.res{n}, "));
var result = $"new(inner.k0, inner.k1, {fields} outer.day as day{i}, outer.res as res{i})";
query = tables[i].AsQueryable().Join(query, "new(k0, k1)", "new(k0, k1)", result);
}
// вуаля :)foreach (var result in query)
Console.WriteLine(result);
Console.ReadLine();
}
Рано обрадовался. Моих знаний явно не хватает, чтобы переделать класс в роу.
// fill dt1
DataTable dt1 = new DataTable();
dt1.Columns.Add("k0", typeof(int));
dt1.Columns.Add("k1", typeof(string));
dt1.Columns.Add("day", typeof(int));
dt1.Columns.Add("res", typeof(int));
for (int i = 0; i < 5; i++)
{
int k0 = i;
string k1 = (i * 2).ToString();
int day = i * 10;
int res = i * 11;
dt1.Rows.Add(new object[] { k0, k1, day, res });
}
// fill dt2
DataTable dt2 = dt1.Clone();
for (int i = 0; i < 5; i++)
{
int k0 = i;
string k1 = (i * 2).ToString();
int day = i * 10 + 3;
int res = i * 11 + 3;
dt2.Rows.Add(new object[] { k0, k1, day, res });
}
List<DataTable> dtList = new List<DataTable>();
dtList.Add(dt1);
dtList.Add(dt2);
query =
dtList[0].AsEnumerable().AsQueryable().
Select("new(k0, k1, day as day0, res as res0)");
Вот этот вот фрагмент заканчивается исключением "System.Linq.Dynamic.ParseException" в DynamicJoin.exe
Дополнительные сведения: No property or field 'k0' exists in type 'DataRow'
Может в этом джойне и нельзя использовать роу и надо все решать через классы?
Рано обрадовался. Моих знаний явно не хватает, чтобы переделать класс в роу.
// fill dt1
DataTable dt1 = new DataTable();
dt1.Columns.Add("k0", typeof(int));
dt1.Columns.Add("k1", typeof(string));
dt1.Columns.Add("day", typeof(int));
dt1.Columns.Add("res", typeof(int));
for (int i = 0; i < 5; i++)
{
int k0 = i;
string k1 = (i * 2).ToString();
int day = i * 10;
int res = i * 11;
dt1.Rows.Add(new object[] { k0, k1, day, res });
}
// fill dt2
DataTable dt2 = dt1.Clone();
for (int i = 0; i < 5; i++)
{
int k0 = i;
string k1 = (i * 2).ToString();
int day = i * 10 + 3;
int res = i * 11 + 3;
dt2.Rows.Add(new object[] { k0, k1, day, res });
}
List<DataTable> dtList = new List<DataTable>();
dtList.Add(dt1);
dtList.Add(dt2);
query =
dtList[0].AsEnumerable().AsQueryable().
Select("new(k0, k1, day as day0, res as res0)");
Вот этот вот фрагмент заканчивается исключением "System.Linq.Dynamic.ParseException" в DynamicJoin.exe
Дополнительные сведения: No property or field 'k0' exists in type 'DataRow'
Может в этом джойне и нельзя использовать роу и надо все решать через классы?
Здравствуйте, abb269, Вы писали:
A> Select("new(k0, k1, day as day0, res as res0)");
Select("new(ItemArray[0] as k0, ItemArray[1] as k1, ItemArray[2] as day0, ItemArray[3] as res0)")
или Select("new(it[\"k0\"] as k0, it[\"k1\"] as k1, it[\"day\"] as day0, it[\"res\"] as res0)")
Здравствуйте, _Raz_, Вы писали:
_R_>Здравствуйте, abb269, Вы писали:
A>> Select("new(k0, k1, day as day0, res as res0)");
_R_>Select("new(ItemArray[0] as k0, ItemArray[1] as k1, ItemArray[2] as day0, ItemArray[3] as res0)") _R_>или _R_>Select("new(it[\"k0\"] as k0, it[\"k1\"] as k1, it[\"day\"] as day0, it[\"res\"] as res0)")
_Raz_, большое спасибо!
Но теперь все равно исключение дальше, которое сильнее меня:
// fill dt1
DataTable dt1 = new DataTable();
dt1.Columns.Add("k0", typeof(int));
dt1.Columns.Add("k1", typeof(string));
dt1.Columns.Add("day", typeof(int));
dt1.Columns.Add("res", typeof(int));
for (int i = 0; i < 5; i++)
{
int k0 = i;
string k1 = (i * 2).ToString();
int day = i * 10;
int res = i * 11;
dt1.Rows.Add(new object[] { k0, k1, day, res });
}
// fill dt2
DataTable dt2 = dt1.Clone();
for (int i = 0; i < 5; i++)
{
int k0 = i;
string k1 = (i * 2).ToString();
int day = i * 10 + 3;
int res = i * 11 + 3;
dt2.Rows.Add(new object[] { k0, k1, day, res });
}
List<DataTable> dtList = new List<DataTable>();
dtList.Add(dt1);
dtList.Add(dt2);
query =
dtList[0].AsEnumerable().AsQueryable().
Select("new(it[\"k0\"] as k0, it[\"k1\"] as k1, it[\"day\"] as day0, it[\"res\"] as res0)");
foreach (var i in Enumerable.Range(1, 3 - 1))
{
var fields = string.Join(
"",
Enumerable.Range(0, i).Select(n => $"inner.day{n}, inner.res{n}, ")
);
var result = $"new(inner.k0, inner.k1, {fields} outer.day as day{i}, outer.res as res{i})";
// тут в query вот так
// "System.Linq.Dynamic.ParseException" в DynamicJoin.exe
// Дополнительные сведения: Expression is missing an 'as' clause
query = dtList[i].AsEnumerable().AsQueryable().
Join(query,
"new(new(it[\"k0\"] as k0, it[\"k1\"] as k1)",
"new(new(it[\"k0\"] as k0, it[\"k1\"] as k1)",
result);
}
string sr = "";
foreach (var result in query)
sr += result + "\n";
Если Join(query, "new(k0, k1)", "new(k0, k1)", result), то ожидаемо получаю:
No property or field 'k0' exists in type 'DataRow'
Здравствуйте, abb269, Вы писали:
A>Если Join(query, "new(k0, k1)", "new(k0, k1)", result), то ожидаемо получаю: A> No property or field 'k0' exists in type 'DataRow'
Для DataRow можно переименовать колонки:
static DataTable BuildTable(int n)
{
var dt = new DataTable();
dt.Columns.Add("k0", typeof(string));
dt.Columns.Add("k1", typeof(string));
dt.Columns.Add("day", typeof(int));
dt.Columns.Add("res", typeof(int));
dt.Rows.Add("0", "42", n * 10, n * 100);
dt.Rows.Add("1", "43", n * 20, n * 200);
dt.Rows.Add("2", "44", n * 30, n * 300);
return dt;
}
const int N = 3;
static void Main(string[] args)
{
var tables = Enumerable.Range(0, N).Select(n => BuildTable(n).AsEnumerable()).ToList();
IQueryable query = tables[0].AsQueryable().Select("new(get_Item(0) as k0, get_Item(1) as k1, get_Item(2) as day0, get_Item(3) as res0)");
foreach (var i in Enumerable.Range(1, N - 1))
{
var fields = string.Join("", Enumerable.Range(0, i).Select(n => $"inner.day{n}, inner.res{n}, "));
var select = $"new(inner.k0, inner.k1, {fields} outer.day as day{i}, outer.res as res{i})";
query =
tables[i].AsQueryable()
.Select("new(get_Item(0) as k0, get_Item(1) as k1, get_Item(2) as day, get_Item(3) as res)")
.Join(query, "new(k0, k1)", "new(k0, k1)", select);
}
foreach (var result in query)
Console.WriteLine(result);
Console.ReadLine();
}
Здравствуйте, bnk, Вы писали:
bnk>Можно добавить "typeof(Data.DataRow)" в список "predefinedTypes", или "get_Item(X)" заменить на "ItemArray[X]". Должно завестить!
Завелось, очень даже. Огромное спасибо Вам за помощь!
На работе небольшой тотализатор, обещаю ставить только на Австрию
Здравствуйте, abb269, Вы писали:
A>Здравствуйте, A>Имеется несколько таблиц одинаковой структуры (столбцы k0, k1, day и res). A>Нужно объединить значения 2..N таблиц со одинаковыми значениями k0 и k1, т.е. получить таблицу вида: A> k0_табл1 k1_табл1 day_табл1 res_табл1 day_табл2 res_табл2 ... day_таблN res_таблN
1. Является ли (k0, k1) первичным ключом в каждой таблице?
2. Бывает ли так, что в какой-то из таблиц нету какого-то из значений (k0, k1)?
3. Зачем вам именно такая структура? Почему бы не разворачивать на клиенте, построив запрос через union all?
4. Откуда взялось переменное число параметров? В вашем запросе параметров вовсе нет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.