Update: I have got a sql query working but am still having trouble converting it to linq2sql. Please see the code below..
I have a linq query that is pulling a lot of data but sometimes it times out due to the load it puts on the sql server. I am going to work on getting more efficient data (adding indexes etc) but I have also heard that using group by would be more efficient than using the sub query. Would a group by be more efficient and if so what would my query below look like with a group by? I am not familiar with group by yet. Please dont use lambda
Edit: New query which is still slow and can time out:
var query = (from s in db.ZipCodeServiceAvailabilities
join a in db.pdx_apart_views on s.ZipCode equals a.Zip_Code.Substring(0, 5) into a_join
from a in a_join.DefaultIfEmpty()
join b in db.ZipCodeBoundaries on s.ZipCode equals b.ZipCode into b_join
from b in b_join.DefaultIfEmpty()
where
(s.IsServiced == 1 &&
b.Ordering % 10 == 0 &&
s.State == "AL")
group new { s, b, a } by new
{
s.ZipCode,
s.IsServiced,
b.Longitude,
b.Latitude,
b.Ordering
} into g
orderby
g.Key.ZipCode,
g.Key.Ordering
select new
{
g.Key.ZipCode,
apartCount = g.Count(p => p.a.Apartment_complex != null),
Longitude = g.Key.Longitude,
Latitude = g.Key.Latitude
}).ToArray();
Edit: Query working in sql that I want in linq2sql (very fast):
select s.ZipCode, count(distinct ident) ApartCount, b.Longitude, b.Latitude from ZipCodeServiceAvailability s
left join pdx_apart_view
on s.ZipCode = left([Zip Code], 5)
left join ZipCodeBoundaries b
on s.ZipCode = b.ZipCode
Where IsServiced = 1 and and Ordering % 10 = 0 and State = 'AL'
Group By s.ZipCode, IsServiced, b.Longitude, b.Latitude, b.Ordering
Order by s.ZipCode, b.Ordering
Original query that is very slow:
var zips = (from s in db.ZipCodeServiceAvailabilities
join b in db.ZipCodeBoundaries on s.ZipCode equals b.ZipCode
where (s.IsServiced == service
&& b.Ordering % 10 == 0
&& s.State.Contains(state))
orderby b.ZipCode
select new
{
zipCode = b.ZipCode.Trim(),
latitude = b.Latitude,
longitude = b.Longitude,
apartCount = (from a in db.pdx_apart_views
where a.Zip_Code.Remove(5) == b.ZipCode
select a.Apartment_complex).Count()
}).ToArray();
Do you mean that you are not familiar with grouping in general, or only in the linq context?
I find it easier to write plain SQL than linq when I don't have the entity definitions, and below is what I think you are looking for in SQL - converting back to linq should be fairly straight-forward.
select
b.ZipCode zipCode,
b.Latitude latitude,
b.Longitude longitude,
count(a.Apartment_complex) apartCount
from
ZipCodeServiceAvailabilities s
join ZipCodeBoundaries b
on s.ZipCode = b.ZipCode
left join pdx_apart_views a
on substring(a.Zip_Code, 1, 5) = b.ZipCode
group by
ZipCode,
Latitude,
Longitude
There was no way to duplicate the left[(zip code), 5] sql method in linq2sql without breaking the index. The answer was to go with straight ado.net so I get all sql functionality.
Related
I want to convert this SQL code to LINQ. Here is my SQL code:
SELECT Rooms.RoomName AS RoomNo, Beds.BedName AS Beds, Rooms.RoomType, ISNULL(CheckIn.CheckIntatus,'') AS Status
FROM CheckIn
INNER JOIN GuestBeds ON CheckIn.GuestBedId = GuestBeds.Id
AND (CheckIn.CheckInStatus = 1 OR CheckIn.CheckIntatus = 2 OR CheckIn.CheckSIntatus = 3)
RIGHT JOIN Beds ON GuestBeds.BedId = Beds.Id
INNER JOIN Rooms ON Beds.RoomId = Rooms.Id
LEFT JOIN Guests ON CheckIn.GuestId = Guests.Id
WHERE Beds.Active = 1 AND Rooms.Active = 1
ORDER BY RoomName, Beds
It works well which means it shows all the RoomName with CheckInStatus. If the Room is not presence in CheckIn table, ot will return the status as Null.
So I want to convert the code to LINQ. SO here is my LINQ code:
from b in Beds
join w in Rooms on b.RoomsId equals w.Id
where (a.CheckInStatus == 3 || a.CheckInStatus == 1 || a.CheckInStatus == 2)
join p in GuestBeds on b.Id equals p.BedId
join a in CheckIn on p.Id equals a.GuestBedId
join t in Guests on a.GuestId equals t.Id
where b.Active == true && w.Active == true
orderby w.RoomName
select new
{
RoomName = w.RoomName,
BedName = b.BedName,
Status = a.CheckInStatus
}
It didnt worked like the first code. It only show the data which contain CheckInStatus. I want it to show all the RoomName inside Room database
Normally I would post some rules for converting SQL to LINQ but this is complicated enough I think I'd need to make new rules. I commented out the references to Guests because as a LEFT JOIN it has no bearing on the answer.
Pull out the WHERE on individual tables and make them sub-queries:
var ActiveBeds = Beds.Where(b => b.Active == 1);
var ActiveRooms = Rooms.Where(r => r.Active == 1);
In LINQ, a RIGHT JOIN must be done by flipping the join to be a left join, so we will create the two sides as sub-queries.
Left side of RIGHT JOIN:
Translate the JOIN conditions that aren't part of an equi-join into a LINQ where clause on the appropriate tables (alternately this could be a subquery as above). The LEFT JOIN becomes a LINQ join/from ... DefaultIfEmpty() phrase, but as noted above isn't needed.
var CheckInsGuestBedsGuests = from c in CheckIn
where (c.CheckInStatus == 1 || c.CheckInStatus == 2 || c.CheckInStatus == 3)
join gb in GuestBeds on c.GuestBedId equals gb.Id
//join g in Guests on c.GuestId equals g.Id into gj
//from g in gj.DefaultIfEmpty()
select new { c, gb /*, g */ };
Right side of RIGHT JOIN:
The other side of the RIGHT JOIN includes an INNER JOIN so put them together in a sub-query:
var ActiveBedsRooms = from b in ActiveBeds
join r in ActiveRooms on b.RoomId equals r.Id
select new { b, r };
Finally, flip the sub-queries to create a left join using the same idiom as above:
var ans = from br in ActiveBedsRooms
join cgbg in CheckInsGuestBedsGuests on br.b.Id equals cgbg.gb.BedId into cgbgj
from cgbg in cgbgj.DefaultIfEmpty()
select new {
RoomNo = br.r.RoomName,
Beds = br.b.BedName,
br.r.RoomType,
Status = cgbg.c.CheckInStatus
};
NOTE: If you were not using LINQ to SQL, the Status expression would fail when cgbg is null and you would need
Status = cgbg?.c.CheckInStatus
but unfortunately LINQ to SQL/EF doesn't handle the null conditional operators yet.
BTW, nice query - brings back memories of when I used to write hotel front desk software :)
I have been trying to convert this SQL statement into a linq as i am trying to move the functionality into a program.
Here is the SQL statement
SELECT cust.sg_group_name AS customer,
(SELECT Sum(du.used_space)
FROM sg_groups AS clnt
LEFT JOIN client_disk_usage AS du
ON clnt.sg_group_id = du.sg_group_id
AND clnt.group_role_id = 3
WHERE clnt.parent_group_id = cust.sg_group_id
AND du.day_of_month = 15
AND du.month_of_year = 05
AND du.used_space_year = 2016) AS disk_usage
FROM sg_groups AS cust
WHERE cust.group_role_id = 2
ORDER BY cust.sg_group_name
Essentially the output is just a list with two columns
customer disk_usage
Customer1 136401537652
Customer2 42208008210
If possible i just want to convert this to a linq statement. I have tried putting the query into LinqPad, but it doesn't seem to want to convert from SQL to Linq (just comes up with a blank white page). I have had a crack at the query myself, but i either get something that doesn't work altogether, or an incorrect number of results.
If anyone has any suggestions that would be great!
disk_usage(Sub Query) is a bit Complicated Part. Converted over here. Try this out
var CoreList = (from clnt in EntityName.sg_groups
join du in EntityName.client_disk_usage
on new { GrpId = clnt.sg_group_id, RoleId = clnt.group_role_id } equals new { GrpId = du.sg_group_id, RoleId = 3 } into LJ
from RT in LJ.DefaultIfEmpty()
where du.day_of_month == 15 && du.month_of_year == 05 && du.used_space_year == 2016
select new {clnt, du, RT}
).ToList();
var CoreListSet = CoreList.Select(i=> new YourEntityClass
{
//Fetch the ParentGroupId & UsedSpace
}).ToList();
var CoreListComplete = (from cl in CoreListSet
join cust in EntityName.sg_groups
on cust.sg_group_id equals cl.parent_group_id).ToList();
Now get the sum of CoreListComplete & just implement the base Select Query in Linq!
Apologies for the delayed response. I've marked #Anil answer up as this is the one that helped me find the answer. You solution did work #Sathish but it can be accomplished in a single command. Here is my final solution. Many thanks for your help!
storeGridUsage = (
from cust in db.sg_groups
from client in db.sg_groups
join du in db.client_disk_usage on client.SG_GROUP_ID equals du.SG_GROUP_ID
where client.GROUP_ROLE_ID == 3
where client.PARENT_GROUP_ID == cust.SG_GROUP_ID && du.DAY_OF_MONTH == day && du.MONTH_OF_YEAR == month && du.USED_SPACE_YEAR == year
where cust.GROUP_ROLE_ID == 2
orderby cust.SG_GROUP_NAME
group new {cust, du} by cust.SG_GROUP_NAME
into g
select new StoreGridUsage
{
CustomerName = g.Key,
DiskUsageInBytes = g.Sum(o => o.du.USED_SPACE)
}).ToList();
I just want the apartment complex count along with the other values. Only adding the count breaks the code. The error I get is "Sequence operators not supported for type 'System.String'." I have also tried changing apartCount to an int with no luck. Any help would be appreciated
using (var db = new DataClasses2DataContext())
{
var zips = (from s in db.ZipCodeServiceAvailabilities
join b in db.ZipCodeBoundaries on s.ZipCode equals b.ZipCode
join a in db.pdx_apart_views on s.ZipCode equals a.Zip_Code
where (s.IsServiced == 1 && b.Ordering % 10 == 0)
orderby b.ZipCode
select new
{
zipCode = b.ZipCode.Trim(),
latitude = b.Latitude,
longitude = b.Longitude,
apartCount = a.Apartment_complex.Count()
}).ToArray();
}
I think you miss group by clause in your query.
or you can use corolated sub query in select clause. please explain your question more
i'm starter in linq, i have write this T-SQL Query
select * from DOCUMENT_TYPES where document_id in(
select document_id from Clearance_Document where Clearance_id=(select clearance_id from clearance_id from request where request_id=3))
i want convert this T-SQL Query to linq, please help me, thanks
Well, I would start first by refactoring your SQL into something other than a chain of nested sub-queries. I think this ought to do the same thing, and it's much more readable:
SELECT
*
FROM
DOCUMENT_TYPES dt
JOIN
Clearance_Document cd
ON
dt.document_id = cd.document_id
JOIN
Request r
ON
cd.clearance_id = r.clearance_id
WHERE
r.request_id = 3
(I'm assuming that from clearance_id from request was a typo.)
Then you can easily refactor into a LINQ statement:
var result = from dt in DOCUMENT_TYPES
join cd in Clearance_Document on dt.document_id equals cd.document_id
join r in Request on cd.clearance_id equals r.clearance_id
where r.request_id = 3
select new {
property1 = dt.something,
property2 = cd.somethingElse,
...
};
var result =
from a in DOCUMENT_TYPES
let list =
(
from b in Clearance_Document
where b.Clearance_id == (from c in clearance_id where request_id == 3).First<string>())
select b
).ToList()
where list.Contains(a.document_id)
select a;
Something like that should do (i guessed you're using EF, but you can easyly adapt to other LinQ-Types):
context.Document_Types.Where(doc =>
conext.Clearance_Document.Where(cd =>
cd.Clearance_Id == context.Request.Single(r => r.Request_Id == 3)
).Contains(doc.Document_Id)
).ToList();
How about
var result = c.Id context.Request.Single(r => r.Id == 3)
.Clearances.SelectMany(c => x.DocumentTypes);
In effect, get the one and only Request with an Id equal to 3, then get all the DocumentTypes of all its Clearances.
If your database is set up with the appropriate foreign keys these relationships will be automatically generated as part of your model.
Here's the query I'm trying to convert into Linq:
SELECT R.Code,
R.FlightNumber,
S.[Date],
S.Station,
R.Liters,
SUM(R.Liters) OVER (PARTITION BY Year([Date]), Month([Date]), Day([Date])) AS Total_Liters
FROM S INNER JOIN
R ON S.ID = R.SID
WHERE (R.Code = 'AC')
AND FlightNumber = '124'
GROUP BY Station, Code, FlightNumber, [Date], Liter
ORDER BY R.FlightNumber, [Date]
Thanks for any help.
UPDATE: Here is the Linq code I'm trying it on; I cannot make the OVER PARTITION by Date.
var test =
(from record in ent.Records join ship in ent.Ship on record.ShipID equals ship.ID
orderby ship.Station
where ship.Date > model.StartView && ship.Date < model.EndView && ship.Station == model.Station && record.FlightNumber == model.FlightNumber
group record by new {ship.Station, record.Code, record.FlightNumber, ship.Date, record.AmountType1} into g
select new { g.Key.Station, g.Key.Code, g.Key.FlightNumber, g.Key.Date, AmmountType1Sum = g.Sum(record => record.AmountType1) });
Execute query first without aggregation:
var test =
(from record in ent.Records join ship in ent.Ship on record.ShipID equals ship.ID
orderby ship.Station
where ship.Date > model.StartView && ship.Date < model.EndView && ship.Station == model.Station && record.FlightNumber == model.FlightNumber
select new {ship.Station, record.Code, record.FlightNumber, ship.Date, record.AmountType1};
Then calculate sum
var result =
from row in test
select new {row.Station, row.Code, row.FlightNumber, row.Date, row.AmountType1,
AmountType1Sum = test.Where(r => r.Date == row.Date).Sum(r => r.AmountType1) };
This should produce the same effect as database query. Code above may contain errors, because I wrote it only here.
I've answered a similar thread on: LINQ to SQL and a running total on ordered results
On that thread it was like this:
var withRuningTotals = from i in itemList
select i.Date, i.Amount,
Runningtotal = itemList.Where( x=> x.Date == i.Date).
GroupBy(x=> x.Date).
Select(DateGroup=> DateGroup.Sum(x=> x.Amount)).Single();
In you situation, you might have to join the two tables together first while grouping, then run the same concept above on the joined table result.