I have next table:
MyTable
(
ParentId Integer,
Type Integer,
ProdId String,
Date DateTime,
Status Integer
);
I want to query as next:
var res = from tout in myTable.Where(t1 => t1.Type == 1)
join tin in myTable.Where(t2 => t2.Type != 1)
on tout.ParentId equals tin.ParentId
where tout.ProdId == tin.ProdId && tout.Status > tin.Status
orderby tout.Date
select new MyTableStructure
{
...
};
How to write same as IQueryable using lambda?
Something like this
var query1 = myTable.Where(t1 => t1.Type == 1);
var query2 = myTable.Where(t2 => t2.Type != 1);
var join = query1.Join(query2, x => x.ParentId, y => y.ParentId, (query1, query2) => new { query1 , query2 }).Where(o => o.query1.ProdId == o.qyuery2.prodId).......
your order by next and Something
Related
I am using entityFramework Core and got a LINQ query select, inner join, where and got the results. I need to add GroupBy and it an error. I followed a few posts and mimic their code but I have been stucked.
I am having issue with translating to LINQ
Here is my linq that is working without the GroupBy
var result = this.myDbContent.Table1
.Join(this.Table2,
table1 => table1.myId,
table2 => table2.myId,
(table1 ,table2) => {table1 ,table2}
)
.Join(this.Table3,
table1_table2 => table1_table2.table1.myId,
table3 => table3.myId,
(table1_table2 ,table3) => {tabtable1_table2 e1 ,table3}
)
.Where(
s => s.table1_table2.table1.myId == 1 &&
s.table1_table2.table2.isCompleted == true
)
.Select(s => new
{
MyID = s.table1_table2.table1.myId,
MyDate = s.table1_table2.Table2.CompletedDate
});
This query works and returns records
In the following I added the GroupBy according to another post
var result = this.myDbContent.Table1
.Join(this.Table2,
table1 => table1.myId,
table2 => table2.myId,
(table1 ,table2) => {table1 ,table2}
)
.Join(this.Table3,
table1_table2 => table1_table2.table1.myId,
table3 => table3.myId,
(table1_table2 ,table3) => {tabtable1_table2 e1 ,table3}
)
.Where(
s => s.table1_table2.table1.myId == 1 &&
s.table1_table2.table2.isCompleted == true
)
.GroupBy(s => new
{
MyID = s.table1_table2.table1.myId,
MyDate = s.table1_table2.Table2.CompletedDate
}
)
.Select(s => new
{
MyID = s.Key.myId,
MyDate = s.Key.CompletedDate,
Count = s.Count()
});
When I run this query with the GroupBy, I get an"SYstem.InvalidOperationException
I am trying to add the following SELECT GROUPBY to the working QUERY
Select Count(*) AS Counts, MyID, MYDATE
FROM ( the working query above )
GROUP BY MyID, MYDATE
Thanks
Yourgroup key only has MyID and MyDate fields - the references to the joined tables are gone, so reference those in your select:
.Select(s => new
{
MyID = s.Key.MyID,
MyDate = s.Key.MyDate,
Count = s.Count()
}
Convert it to a list or Enumerable before grouping
var result = this.myDbContent.Table1
.Join(this.Table2,
table1 => table1.myId,
table2 => table2.myId,
(table1 ,table2) => {table1 ,table2}
)
.Join(this.Table3,
table1_table2 => table1_table2.table1.myId,
table3 => table3.myId,
(table1_table2 ,table3) => {tabtable1_table2 e1 ,table3}
)
.Where(
s => s.table1_table2.table1.myId == 1 &&
s.table1_table2.table2.isCompleted == true
).AsEnumerable()
.GroupBy(s => new
{
MyID = s.table1_table2.table1.myId,
MyDate = s.table1_table2.Table2.CompletedDate
}
)
.Select(s => new
{
MyID = s.Key.table1_table2.table1.myId,
MyDate = s.Key.table1_table2.Table2.CompletedDate,
Count = s.Count()
});
Wondering why LINQ doesn't have a Left Join method. I've been trying to figure this out with myriad examples on SO, but no such luck. The other examples show simple examples with one join. If I group the joins then I only get references to the TradeCountries table in the select statement.
Being new to LINQ, I could've had this done 4 hours ago with a simple SELECT statement, but here I'm am trying to figure out why the LeftJoin method was left out of LINQ.
What does the line with "LeftJoin" need to be changed to make this work?
/*
* GetTop5Distributors
#param int array of series IDs
*/
public List<TopDistributors> Get5TopDistributors(IEnumerable<int> seriesIds)
{
_context = new MySQLDatabaseContext();
var result = _context.TradesTrades
.Join(_context.TradesSeries, tt => tt.SeriesId, ts => ts.Id, (tt, ts) => new { tt, ts })
.Join(_context.TradesTradeDistributors, tsd => tsd.tt.Id, ttd => ttd.TradeId,
(tsd, ttd) => new { tsd, ttd })
.Join(_context.TradesOrganisations, tsdto => tsdto.ttd.DistributorId, to => to.Id,
(tsdto, to) => new { tsdto, to })
.LeftJoin(_context.TradesCountries, tsdc => tsdc.to.CountryId, tc => tc.Id,
(tsdc, tc) => new {tsdc, tc})
.Where(x => seriesIds.Contains(x.tsdc.tsdto.tsd.tt.SeriesId))
.Where(x => x.tsdc.tsdto.tsd.tt.FirstPartyId == null)
.Where(x => x.tsdc.tsdto.tsd.tt.Status != "closed")
.Where(x => x.tsdc.tsdto.tsd.tt.Status != "cancelled")
.GroupBy(n => new { n.tsdc.tsdto.tsd.tt.SeriesId, n.tsdc.tsdto.ttd.DistributorId })
.Select(g =>
new TopDistributors
{
SeriesId = g.Key.SeriesId,
DistributorName = g.Select(i => i.tsdc.to.Name).Distinct().First(),
IsinNickname = g.Select(i => i.tsdc.tsdto.tsd.ts.Nickname).Distinct().First(),
CountryName = g.Select(i => i.tc.Name).Distinct().First(),
CommissionTotal = Math.Ceiling(g.Sum(i => i.tsdc.tsdto.ttd.Commission))
}
)
.OrderByDescending(x => x.CommissionTotal)
.Take(5)
.ToList();
return result;
}
Here's the rather simple select statement that is taking orders or magnitude too long to convert to LINQ.
SELECT
trades_trades.series_id,
trades_organisations.`name`,
trades_series.nickname,
trades_countries.name as Country_Name,
SUM(trades_trade_distributors.commission) as Commission_Total
FROM
trades_trades
JOIN trades_series
ON trades_series.id = trades_trades.series_id
JOIN trades_trade_distributors
ON trades_trades.id = trades_trade_distributors.trade_id
JOIN trades_organisations
ON trades_trade_distributors.distributor_id = trades_organisations.id
LEFT JOIN trades_countries
ON trades_organisations.country_id = trades_countries.id
WHERE trades_trades.series_id IN (
17,
18)
AND trades_trades.first_party_id IS NULL
AND trades_trades.status <> 'closed'
AND trades_trades.status <> 'cancelled'
GROUP BY trades_trades.series_id, trades_trade_distributors.distributor_id
ORDER BY Commission_Total DESC
Following my recipe, here is a more or less straightforward translation of the SQL to LINQ. I moved the where to be near what it constrains, and used let to create a convenient name for the Sum, as LINQ doesn't allow you to forward reference anonymous object members.
var ans = from tt in trades_trades
where new[] { 17, 18 }.Contains(tt.series_id) && tt.first_party_id == null &&
tt.status != "closed" && tt.status != "cancelled"
join ts in trades_series on tt.series_id equals ts.id
join ttd in trades_trade_distributors on tt.id equals ttd.trade_id
join to in trades_orginizations on ttd.distributor_id equals to.id
join tc in trades_countries on to.country_id equals tc.id into tcj
from tc in tcj.DefaultIfEmpty() // GroupJoin -> left join
group new { tt, ts, ttd, to, tc } by new { tt.series_id, ttd.distributor_id } into tradeg
let Commission_Total = tradeg.Sum(trade => trade.ttd.commission)
orderby Commission_Total descending
select new {
tradeg.Key.series_id,
tradeg.First().to.name,
tradeg.First().ts.nickname,
Country_Name = tradeg.First().tc == null ? null : tradeg.First().tc.name,
Commission_Total
};
I'm trying to convert my sql query to linq, i confused about sum and grouping,
this is my query
SELECT
produk.supplier,
SUM(transaksi.jumlah_transaksi),
SUM(transaksi.nominal_transaksi),
operasional.nominal
FROM
transaksi INNER JOIN produk ON transaksi.id_produk = produk.id_produk
LEFT JOIN
(SELECT
operasional.id_supplier,
SUM(nominal) AS nominal
FROM
operasional) operasional
ON operasional.id_supplier = produk.id_supplier
GROUP BY produk.supplier
output should be
like this
Progress
i am just trying with linq query like this without grouping
var result = from t in db.transaksi
join p in db.produk on t.id_produk equals p.id_produk
from op in
(
from o in db.operasional
select new
{
id_supplier = o.id_supplier,
nominal = o.nominal
}
).Where(o => o.id_supplier == p.id_supplier).DefaultIfEmpty()
select new
{
nama_supplier = p.supplier,
jumlah_transaksi = t.jumlah_transaksi,
nominal_transaksi = t.nominal_transaksi,
biaya_operasional = op.nominal
};
and result query from my linq still like this
SELECT
`p`.`supplier`,
`t`.`jumlah_transaksi`,
`t`.`nominal_transaksi`,
`t1`.`nominal`
FROM
`transaksi` `t`
INNER JOIN `produk` `p`
ON `t`.`id_produk` = `p`.`id_produk`
LEFT JOIN `operasional` `t1`
ON `t1`.`id_supplier` = `p`.`id_supplier`
Solved
and this is my full linq
var result = from t in db.transaksi
join p in db.produk on t.id_produk equals p.id_produk
from op in
(
from o in db.operasional
group o by o.id_supplier into g
select new
{
id_supplier = g.First().id_supplier,
nominal = g.Sum(o => o.nominal)
}
).Where(o => o.id_supplier == p.id_supplier).DefaultIfEmpty()
select new
{
nama_supplier = p.supplier,
jumlah_transaksi = t.jumlah_transaksi,
nominal_transaksi = t.nominal_transaksi,
biaya_operasional = op.nominal
};
var grouped = result
.GroupBy(x => x.nama_supplier)
.Select(x => new
{
nama_supplier = x.Key,
jumlah_transaksi = x.Sum(s => s.jumlah_transaksi),
nominal_transaksi = x.Sum(s => s.nominal_transaksi),
biaya_operasional = x.Select(s => s.biaya_operasional).First()
});
Try to use GroupBy (in following code result is your query from code above):
var grouped = result
.GroupBy(x => x.nama_supplier)
.Select(x => new {
nama_supplier = x.Key,
sum1 = x.Sum(s => s.jumlah_transaksi),
sum1 = x.Sum(s => s.nominal_transaksi),
nominal = x.Select(s => s.biaya_operasional).First()
})
Code is not checked so use it just as idea.
How to convert following code to method operator:
var myOrders = from c in customers
where c.Field<string>("Region") == "WA"
from o in orders
where c.Field<string>("CustomerID") == o.Field<string>("CustomerID")
&& (DateTime)o["OrderDate"] >= cutoffDate
select new {
CustomerID = c.Field<string>("CustomerID"),
OrderID = o.Field<int>("OrderID")
};
---------or----------
var myOrders = from c in customers
where c.Region == "WA"
from o in orders
where c.CustomerID == o.CustomerID
&& o.OrderDate >= cutoffDate
select new {
CustomerID = c.CustomerID,
OrderID = o.OrderID
};
same code in object form
I'd actually rewrite this as a join - probably via intermediate variables:
var washingtonCustomers = customers.Where(c => c.Field<string>("Region") == "WA");
var recentOrders = orders.Where(o => (DateTime)o["OrderDate"] >= cutoffDate);
var query = washingtonCustomers.Join(recentOrders,
c => c.Field<string>("CustomerID"),
o => o.Field<string>("CustomerID"),
(c, o) => new {
CustomerID = c.Field<string>("CustomerID"),
OrderID = o.Field<int>("OrderID")
});
You can try with this code - based on IEnumerable<KeyValuePair<string, Int32>
public IEnumerable<KeyValuePair<string, Int32>> YourQuery(DateTime date, string code)
{
var result =
from c in customers
where c.Field<string>("Region") == code
from o in orders
where c.Field<string>("CustomerID") == o.Field<string>("CustomerID")
&& (DateTime)o["OrderDate"] >= date
select new
{
CustomerID = c.Field<string>("CustomerID"),
OrderID = o.Field<int>("OrderID")
};
return result;
}
Are you just wanting to use the functional Linq syntax instead of query syntax? That would look like:
var myOrders = customers
.Where(c => c.Region == "WA")
.SelectMany(c =>
orders
.Where(o => (o.CustomerID == c.CustomerID)
&& (o.OrderDate > cutoffDate))
.Select(o => new {
CustomerID = c.CustomerID,
OrderID = o.OrderID
})
);
I have a sp which builds a dynamic sql query based on my input params. I tried replicating in linq and somehow it seems incorrect.
My linq:
var result = from R in db.Committees.Where(committeeWhere)
join C in db.Employees.Where(employeeWhere) on R.PID equals C.PID
join K in db.CommitteeTypes.Where(committeesWhere) on R.PID equals K.PID
select new { R };
The 3 input params i have are:
1. Committee ID and/or
Employee ID and/or
Committee Type ID
Based on this, i want to be able to make the joins in my linq.
Note: i had to change table names and column names so please do not give thought on the names.
Sql snippet:
IF #committeeID is not null
set #wherestr = #wherestr + 'Committees.committeeID like' + #committeeID + #andstr
//...
IF len(#wherestr) > 6
SELECT #qrystr = #selectstr + #fromstr + left(#wherestr, len(#wherestr)-3) + ' ORDER BY Committees.committeeID DESC
EXEC (#qrystr)
Why do you need to use dynamic SQL? Wouldn't this work?
IQueryable<Committee> GetCommittees(int? committeeID, int? employeeID, int? committeeTypeID)
{
var result = from R in db.Committees.Where(c => committeeID == null || committeeID == c.ID)
join C in db.Employees.Where(e => employeedID == null || employeeID == e.ID)
on R.PID equals C.PID
join K in db.CommitteeTypes.Where(c => committeeTypeID == null || committeeTypeID == c.ID)
on R.PID equals K.PID
select R;
}
If that won't work, you can use different predicate expressions depending on your parameters:
Expression<Func<Committee, bool>> committeeWhere;
if(committeeID.HasValue)
{
int id = committeeID.Value;
committeeWhere = c => c.ID == id;
}
else
{
committeeWhere = c => true;
}
// etc
Update: Seeing your last comment, maybe you want something like this:
IQueryable<Committee> GetCommittees(int? committeeID, int? employeeID, int? committeeTypeID)
{
var result = db.Committees.Select(c => c);
if(committeeID.HasValue)
{
result = result.Where(c => c.ID = committeeID);
}
else if(employeeID.HasValue)
{
result = from R in result
join C in db.Employees.Where(e => employeeID == e.ID)
on R.PID equals C.PID
select R;
}
else if(committeeTypeID.HasValue)
{
result = from R in result
join K in db.CommitteeTypes.Where(ct => committeeTypeID == ct.ID)
on R.PID equals K.PID
select R;
}
return result;
}
If I may improve upon dahlbyk's answer... sometimes joining introduces duplicates. If you really intend to filter - then filter. Also - if you add the relationships in the LinqToSql designer, you'll have properties (such as Committee.Employees) which will be translated for you.
IQueryable<Committee> GetCommittees(int? committeeID, int? employeeID, int? committeeTypeID){
IQueryable<Committee> result = db.Committees.AsQueryable();
if(committeeID.HasValue)
{
result = result.Where(c => c.ID = committeeID);
}
if(employeeID.HasValue)
{
result = result
.Where(committee => committee.Employees
.Any(e => employeeID == e.ID)
);
}
if(committeeTypeID.HasValue)
{
result = result
.Where(committee => committee.CommitteeTypes
.Any(ct => committeeTypeID == ct.ID)
);
}
return result;
}