I need help with converting a SQL query to LINQ. I tried with Linqer but that didn't give the expected results. This is my SQL query:
SELECT
dr.startDate,
dr.endDate,
SUM(CASE WHEN me.Size <= 10 THEN 1 ELSE 0 END) AS FirstGroup,
SUM(CASE WHEN me.Size > 10 AND me.Size <= 20 THEN 1 ELSE 0 END) AS SecondGroup,
SUM(CASE WHEN me.Size > 20 AND me.Size <= 30 THEN 1 ELSE 0 END) AS ThirdGroup,
SUM(CASE WHEN me.Size > 30 THEN 1 ELSE 0 END) AS FourthGroup,
MAX(ISNULL(me.Size,0)) AS MaxSize,
SUM(ISNULL(me.Size,0)) AS SpaceTotal
FROM
time_intervals dr
LEFT OUTER JOIN Rooms me
ON ( me.DateTime BETWEEN dr.startDate AND dr.endDate)
GROUP BY
dr.startDate,
dr.endDate
ORDER BY dr.startDate
The LINQ i tried is:
var stats = from t in time_intervals
from q in query
where q.DateTime >= t.startDate && q.DateTime <= t.endDate
select new {
Date = t.startDate,
First = (q.Size <= 10),
Second = (q.Size > 10 && q.Size <= 20),
Third = (q.Size > 20 && q.Size <= 30),
Fourth = (q.Size > 30)
};
But that didn't give the same result as the SQL query.
You are not using group keyword in your LINQ while you are grouping records by by start date and end date.
Try this code:-
var stats = (from t in time_intervals
from q in query.Where(m=> m.DateTime >= t.startDate && m.DateTime <= t.endDate).DefaultIfEmpty()
group q by new { t.startDate, t.endDate, q.Size } into g
select new
{
Date = g.Key.startDate,
First = g.Count(m=>m.Size <= 10)
}).OrderBy(m => m.startDate);
Related
I tried to convert sql query to linq but couldn't get it correctly. Can someone help me to convert below to linq please?
SELECT stockdiary.datenew, locations.ID AS LOCATIONID, locations.NAME AS LOCATIONNAME,
products.REFERENCE, products.NAME,
products.CATEGORY, categories.NAME AS CATEGORYNAME,
products.SUPPLIER,
SUM(CASE WHEN stockdiary.UNITS <0 THEN stockdiary.UNITS ELSE 0 END) AS UNITSOUT,
SUM(CASE WHEN stockdiary.UNITS <0 THEN stockdiary.UNITS * stockdiary.PRICE ELSE 0 END) AS TOTALOUT,
SUM(CASE WHEN stockdiary.UNITS >=0 THEN stockdiary.UNITS ELSE 0 END) AS UNITSIN,
SUM(CASE WHEN stockdiary.UNITS >=0 THEN stockdiary.UNITS * stockdiary.PRICE ELSE 0 END) AS TOTALIN,
SUM(stockdiary.UNITS) AS UNITSDIFF,
SUM(stockdiary.UNITS * stockdiary.PRICE) AS TOTALDIFF
FROM stockdiary JOIN locations ON stockdiary.LOCATION = locations.ID,
products LEFT OUTER JOIN categories ON products.CATEGORY = categories.ID
WHERE products.ID = stockdiary.PRODUCT
GROUP BY locations.ID, locations.NAME, products.REFERENCE, products.NAME, products.CATEGORY, categories.NAME
ORDER BY locations.ID, categories.NAME, products.NAME
======
below is my linq query which gives me wrong result.
(from sd in Stockdiaries
join loc in Locations on sd.Location equals loc.Id
join prod in Products on sd.Product equals prod.Id
join cat in Categories on prod.Category equals cat.Id
select new
{
Location = loc.Name,
Category = cat.Name,
Reference = prod.Reference,
Product = prod.Name,
UnitsOut = sd.Units < 0 ? sd.Units:0,
TotalOut = sd.Units < 0 ? sd.Units * sd.Price:0,
UnitsIn = sd.Units >= 0 ? sd.Units:0,
TotalIn = sd.Units >= 0 ? sd.Units * sd.Price:0,
UnitsDiff = sd.Units,
TotalDiff = sd.Units * sd.Price
})
You've got some old join syntax in that original sql! This is in addition to the left join. This is abbreviated here:
from stockdiary
join locations on stockdiary.location = locations.id
, products
left join categories on products.category = categories.id
where products.id = stockdiary.product
See if the following approach works out for you. It may not output exactly as you desire it, but it's hopefully close and sufficient for you to work with it after that. Although that being said, I don't have any sample data from you on which to test it, so the only thing I can confirm right now is that it won't error out.
I've got comments within the code describing its components.
var query =
from sd in Stockdiaries
join loc in Locations on sd.Location equals loc.Id
// Your old syntax join should work like an inner join
join prod in Products on sd.Product equals prod.Id
// This is a left join. So you've got to do the 'into' hoop and
// then 'overwrite' the cat table.
join cat in Categories on prod.Category equals cat.Id into pCat
from cat in pCat.DefaultIfEmpty()
// put it all together into one result set
select new {
Location = loc.Name,
Category = cat?.Name, // Because it's a left join, it may be null, hence the '?'
Reference = prod.Reference,
Product = prod.Name,
sd.Units,
sd.Price
} into cnd
// group as appropriate, and remember that in linq
// grouping is a separate operation from aggregation
group cnd by new { cnd.Location, cnd.Reference, cnd.Product, cnd.Category } into g
// aggregate
select new {
g.Key.Location,
g.Key.Reference,
g.Key.Product,
g.Key.Category,
UnitsOut = g.Sum(row => row.Units < 0 ? row.Units : 0),
TotalOut = g.Sum(row => row.Units < 0 ? row.Units * row.Price : 0),
UnitsIn = g.Sum(row => row.Units >= 0 ? row.Units : 0),
TotalIn = g.Sum(row => row.Units >= 0 ? row.Units * row.Price : 0),
UnitsDiff = g.Sum(row => row.Units),
TotalDiff = g.Sum(row => row.Units * row.Price)
};
query.Dump();
#pwilcox and all other friends,
Here is the final linq query which gave me the absolute result! I added orderby expression in addition to the above query.
(from sd in Stockdiaries
join loc in Locations on sd.Location equals loc.Id
join prod in Products on sd.Product equals prod.Id
join cat in Categories on prod.Category equals cat.Id into pCat
from cat in pCat.DefaultIfEmpty()
select new {
Location = loc.Name,
Category = cat.Name,
Reference = prod.Reference,
Product = prod.Name,
sd.Units,
sd.Price
} into cnd
group cnd by new {cnd.Location,cnd.Reference, cnd.Product, cnd.Category} into g
orderby g.Key.Location, g.Key.Category, g.Key.Product
select new {
g.Key.Location,
g.Key.Reference,
g.Key.Product,
g.Key.Category,
UnitsOut = g.Sum(row => row.Units < 0 ? row.Units : 0),
TotalOut = g.Sum(row => row.Units < 0 ? row.Units * row.Price : 0),
UnitsIn = g.Sum(row => row.Units >= 0 ? row.Units : 0),
TotalIn = g.Sum(row => row.Units >= 0 ? row.Units * row.Price : 0),
UnitsDiff = g.Sum(row => row.Units),
TotalDiff = g.Sum(row => row.Units * row.Price)
})
Hy. I'm working on a query, which should join 3 tables like
client - has ID - take his name
banking - has clientid - take some data from bankDate to bankDate
marketing - has clientid - take some data from marketDate to marketDate
code:
var totals = from client in _db.Clients
join bank in _db.Banking on client.Id equals bank.ClientId
where (client.Id == bank.ClientId &&
DateTime.Compare(bank.BankDate, (DateTime) fromDate) >= 0 &&
DateTime.Compare(bank.BankDate, (DateTime) toDate) <= 0)
join market in _db.Marketing on client.Id equals market.ClientId
where (client.Id == market.ClientId &&
DateTime.Compare(market.MarketDate, (DateTime) fromDate) >= 0 &&
DateTime.Compare(market.MarketDate, (DateTime) toDate) <= 0)
select new {client.Username, bank, market};
This algorithm doesn't provide successful join for the tables with many-to-one relations.
Who has ever faced this problem and knows how to solve it? I'll be very appreciated for any help
I am assuming that the where statement is not referencing the correct table.
Try this: (might be syntax error)
var totals = from client in _db.Clients
join bank in _db.Banking.Where(x => DateTime.Compare(x.BankDate, (DateTime) fromDate) >= 0 &&
DateTime.Compare(x.BankDate, (DateTime) toDate) <= 0) on client.Id equals bank.ClientId
join market in _db.Marketing.Where(x => DateTime.Compare(x.MarketDate, (DateTime) fromDate) >= 0 &&
DateTime.Compare(x.MarketDate, (DateTime) toDate) <= 0) on client.Id equals market.ClientId
select new {client.Username, bank, market};
By many-to-one I guess you are looking for left outer join, try this.
var totals = from client in _db.Clients
join bank in _db.Banking on client.Id equals bank.ClientId into banks
from bank in banks.DefaultIfEmpty()
where (client.Id == bank.ClientId &&
DateTime.Compare(bank.BankDate, (DateTime)fromDate) >= 0 &&
DateTime.Compare(bank.BankDate, (DateTime)toDate) <= 0)
join market in _db.Marketing on client.Id equals market.ClientId into markets
from market in markets.DefaultIfEmpty()
where (client.Id == market.ClientId &&
DateTime.Compare(market.MarketDate, (DateTime)fromDate) >= 0 &&
DateTime.Compare(market.MarketDate, (DateTime)toDate) <= 0)
select new { client.Username, bank, market };
Wish to convert this to LINQ.
select COUNT(*) as 'BillsOver30' from pssuite_web.pujhaccd
where billdays>30 and DATEDIFF(month,'07-07-2016', GETDATE()) <= 13
Group By Month(billdate)
This will show 13 rolling months from 07-07 with how many bills were over 30 for each month.
This is the terrible query I've written in LINQ, which doesn't work:
DateTime earliestDate = objdate1.DateStart.Value.AddMonths(-13);
var custQuery9 = ((from m in DataContext.pujhaccds
where m.billdays > 30
&& m.billdate >= earliestDate
&& m.billdate <= objdate1.DateStart
group m by m.billdays into p
select p)).Count();
To get result as you described in comments:
var result = (from m in DataContext.pujhaccds
where m.billdays > 30 &&
m.billdate >= earliestDate &&
m.billdate <= objdate1.DateStart
group m by m.billdate.Month into p
select new { Month = p.Key, Count = p.Count() }).ToList();
To get it like in original question replace the select above like this:
select p.Count()
That grouping will be problematic though if you have data from different years and want to separate it. If that is the case group by 2 fields - year and month:
var result = (from m in DataContext.pujhaccds
where m.billdays > 30 &&
m.billdate >= earliestDate &&
m.billdate <= objdate1.DateStart
group m by new { m.billdate.Value.Month, m.billdate.Value.Year } into p
select new { Date = $"{p.Key.Month} - {p.Key.Year}", Count = p.Count() }).ToList();
Why does the single where query give a different result than multiple where queries ?
query.Where("666 = ID");
query.Where("ActiveFrom < #0 && ActiveTo > #1 && ValidFrom < DateTime.Now && ValidTo > DateTime.Now", toDate, fromDate);
query.ToString(); results in :
SELECT *
FROM [Country] AS [Extent1]
WHERE 666 = [Extent1].[ID]
and the same query with multiple where calls
query = query.Where("ActiveFrom < #0", toDate);
query = query.Where("ActiveTo > #0", fromDate);
query = query.Where("ValidFrom < DateTime.Now");
query = query.Where("ValidTo > DateTime.Now");
results in :
SELECT *
FROM [Country] AS [Extent1]
WHERE (666 = [Extent1].[ID]) AND
([Extent1].[ActiveFrom] < convert(datetime2, '2016-10-23 11:40:35.9538054', 121)) AND
([Extent1].[ActiveTo] > convert(datetime2, '2016-06-23 11:40:35.9518052', 121)) AND
([Extent1].[ValidFrom] < (SysDateTime())) AND
([Extent1].[ValidTo] > (SysDateTime()))
In order for the different Wheres to be relevant you need to assign them back to query:
//instead of:
query.Where("666 = ID");
query.Where("ActiveFrom < #0 && ActiveTo > #1 && ValidFrom < DateTime.Now && ValidTo > DateTime.Now", toDate, fromDate);
//do:
query = query.Where("666 = ID");
query = query.Where("ActiveFrom < #0 && ActiveTo > #1 && ValidFrom < DateTime.Now && ValidTo > DateTime.Now", toDate, fromDate);
Also the Where calls can be chained. Most linq extension methods return IEnumerable<TSource> and therefore can be chained.
Applying the chaining on your second query it will look like this:
query = query.Where("ActiveFrom < #0", toDate)
.Where("ActiveTo > #0", fromDate)
.Where("ValidFrom < DateTime.Now")
.Where("ValidTo > DateTime.Now");
Because the calls dont modify the query, they return a new instance representing the modified query instead. Thus the second example results in the big query whereas the first results in a simple where condition only.
I'm really struggling with LINQ. I've written my query out in SQL (in effect it's a pivot), and trying to write an equivalent statement in LINQ. Any pointers forward would be much appreciated. See below for code:
SELECT b.URL,
SUM(CASE WHEN (a.ExtFlag = 0) THEN 1 ELSE 0 END) AS IntLinks,
SUM(CASE WHEN (a.ResponseCode >= 400 AND a.ExtFlag = 0) THEN 1 ELSE 0 END) AS IntBroken,
SUM(CASE WHEN (a.ExtFlag = 1) THEN 1 ELSE 0 END) AS ExtLinks,
SUM(CASE WHEN (a.ResponseCode >= 400 AND a.ExtFlag = 1) THEN 1 ELSE 0 END) AS ExtBroken
FROM Link a
INNER JOIN Host b
ON a.HostID = b.ID
GROUP BY b.URL
ORDER BY b.URL
Many Thanks.
I think this should do what you want - it's at least worth a try:
var query = from link in db.Links
join host in db.Hosts on link.HostID equals host.ID
group link by host.Url into links
select new
{
Url = links.Url,
IntLinks = links.Count(link => link.ExtFlag == 0),
IntBroken = links.Count(link => link.ExtFlag == 0 &&
link.ResponseCode >= 400),
ExtLinks = links.Count(link => link.ExtFlag == 1),
ExtBroken = links.Count(link => link.ExtFlag == 1 &&
link.ResponseCode >= 400),
};
This is how to do it:
from a in db.Links
group a by a.Host.Url into g
select new
{
Url = g.Key,
IntLinks = (
from x in g
select x.ExtFlag == 0 ? 1 : 0)
.Sum()
};
You can use the ?: operator for your CASE.