I have an entity framework query to join applications with ethnicity table and group by ethnicity (Id and options) and then get the total count for each ethnicity and then get the individual counts based on status {open, Closed, Draft.. etc) with Iqueryable as I will need to use pagination for this query to get first 'x' or go to page 'y' so I cannot do toList and then get the values.
The current EF query is very slow and it's taking more time.
Can anyone help me to achieve the same result in a better way if possible?
var query = from app in Context.Application
join eth in Context.Ethnicities on app.EthnicityId equals eth.EthnicityId
group app by new
{
eth.EthnicityId,
eth.EthnicityOptions
}
into ethAgg
select new EthnicityView
{
Id = ethAgg.Key.EthnicityId,
Ethnicity = ethAgg.Key.EthnicityOptions,
Total = ethAgg.Count(),
Closed = ethAgg.Count(p => p.Closed),
Draft = ethAgg.Count(p => p.Draft ),
Inprogress = ethAgg.Count(p => p.Inprogress ),
Waiting = ethAgg.Count(p => p.Waiting),
Open = ethAgg.Count(p => p.Open )
};
Generated Sql
SELECT TOP (10)
[Project7].[EthnicityID] AS [EthnicityID],
[Project7].[C2] AS [C1],
[Project7].[C1] AS [C2],
[Project7].[C3] AS [C3],
[Project7].[C4] AS [C4],
[Project7].[C5] AS [C5],
[Project7].[C6] AS [C6],
[Project7].[C7] AS [C7]
FROM ( SELECT
[Project6].[C1] AS [C1],
[Project6].[EthnicityID] AS [EthnicityID],
[Project6].[EthnicityOptions] AS [C2],
[Project6].[C2] AS [C3],
[Project6].[C3] AS [C4],
[Project6].[C4] AS [C5],
[Project6].[C5] AS [C6],
[Project6].[C6] AS [C7]
FROM ( SELECT
[Project5].[C1] AS [C1],
[Project5].[EthnicityID] AS [EthnicityID],
[Project5].[EthnicityOptions] AS [EthnicityOptions],
[Project5].[C2] AS [C2],
[Project5].[C3] AS [C3],
[Project5].[C4] AS [C4],
[Project5].[C5] AS [C5],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent16]
INNER JOIN [dbo].[Ethnicity] AS [Extent18] ON [Extent16].[EthnicityID] = [Extent18].[EthnicityID]
WHERE ([Extent16].[Closed] = 1)
FROM ( SELECT
[Project4].[C1] AS [C1],
[Project4].[EthnicityID] AS [EthnicityID],
[Project4].[EthnicityOptions] AS [EthnicityOptions],
[Project4].[C2] AS [C2],
[Project4].[C3] AS [C3],
[Project4].[C4] AS [C4],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent13]
INNER JOIN [dbo].[Ethnicity] AS [Extent15] ON [Extent13].[EthnicityID] = [Extent15].[EthnicityID]
WHERE ([Extent13].[Closed] = 1)
FROM ( SELECT
[Project3].[C1] AS [C1],
[Project3].[EthnicityID] AS [EthnicityID],
[Project3].[EthnicityOptions] AS [EthnicityOptions],
[Project3].[C2] AS [C2],
[Project3].[C3] AS [C3],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent10]
INNER JOIN [dbo].[Ethnicity] AS [Extent12] ON [Extent10].[EthnicityID] = [Extent12].[EthnicityID]
WHERE ([Extent10].[Draft] = 1)
FROM ( SELECT
[Project2].[C1] AS [C1],
[Project2].[EthnicityID] AS [EthnicityID],
[Project2].[EthnicityOptions] AS [EthnicityOptions],
[Project2].[C2] AS [C2],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent7]
INNER JOIN [dbo].[Ethnicity] AS [Extent9] ON [Extent7].[EthnicityID] = [Extent9].[EthnicityID]
WHERE ([Extent7].[Inprogress] = 1)
FROM ( SELECT
[Project1].[C1] AS [C1],
[Project1].[EthnicityID] AS [EthnicityID],
[Project1].[EthnicityOptions] AS [EthnicityOptions],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent4]
INNER JOIN [dbo].[Ethnicity] AS [Extent6] ON [Extent4].[EthnicityID] = [Extent6].[EthnicityID]
WHERE ([Extent4].[Waiting] = 1)
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[K1] AS [EthnicityID],
[GroupBy1].[K2] AS [EthnicityOptions]
FROM ( SELECT
[Extent3].[EthnicityID] AS [K1],
[Extent3].[EthnicityOptions] AS [K2],
COUNT(1) AS [A1]
FROM [dbo].[Application] AS [Extent1]
INNER JOIN [dbo].[Ethnicity] AS [Extent3] ON [Extent1].[EthnicityID] = [Extent3].[EthnicityID]
GROUP BY [Extent3].[EthnicityID], [Extent3].[EthnicityOptions]
) AS [GroupBy1]
) AS [Project1]
) AS [Project2]
) AS [Project3]
) AS [Project4]
) AS [Project5]
) AS [Project6]
) AS [Project7]
ORDER BY [Project7].[EthnicityID] ASC
As there is no way we could achieve this from entity framework.
I tried moving this query to a stored procedure and split the individual counts and invoke that stored proc from entity framework.
I need to query multiple tables with one query, and I need to limit the results from each table individually.
An example ...
I have a ContentItem, Retailer, and Product table.
ContentItem has a Type (int) field that corresponds to an enum of content types like "Retailer" and "Product." I am filtering ContentItem using this field for each sub-subquery.
ContentItem has an Id (pkey) field.
Retailer and Product have an Id (pkey) field. Id is also an FK to ContentItem.Id.
I can select from all three tables with a LEFT JOIN query. From there, I can then limit the total number of rows returned, let's say 6 rows total.
What I want to do is limit the number of rows returned from Retailer and Product individually. This way, I will have 12 rows (max) total: 6 from Retailer, and 6 from Product.
I can already accomplish this with SQL, but I am having a difficult time getting LINQ-to-Entities to "do the right thing."
Here's my SQL
SELECT * From
(
(SELECT * FROM (SELECT * FROM [dbo].[ContentItem] WHERE Type = 0 ORDER BY ContentItem.mtime OFFSET 0 ROWS FETCH NEXT 6 ROWS ONLY) Retailers)
UNION ALL
(SELECT * FROM (SELECT * FROM [dbo].[ContentItem] WHERE Type = 1 ORDER BY ContentItem.mtime OFFSET 0 ROWS FETCH NEXT 6 ROWS ONLY) Brands)
UNION ALL
(SELECT * FROM (SELECT * FROM [dbo].[ContentItem] WHERE Type = 2 ORDER BY ContentItem.mtime OFFSET 0 ROWS FETCH NEXT 6 ROWS ONLY) Products)
UNION ALL
(SELECT * FROM (SELECT * FROM [dbo].[ContentItem] WHERE Type = 3 ORDER BY ContentItem.mtime OFFSET 0 ROWS FETCH NEXT 6 ROWS ONLY) Certifications)
UNION ALL
(SELECT * FROM (SELECT * FROM [dbo].[ContentItem] WHERE Type = 4 ORDER BY ContentItem.mtime OFFSET 0 ROWS FETCH NEXT 6 ROWS ONLY) Claims)
) as ContentItem
LEFT JOIN [dbo].[Retailer] ON (Retailer.Id = ContentItem.Id)
LEFT JOIN [dbo].[Brand] ON (Brand.Id = ContentItem.Id)
LEFT JOIN [dbo].[Product] ON (Product.Id = ContentItem.Id)
LEFT JOIN [dbo].[Certification] ON (Certification.Id = ContentItem.Id)
LEFT JOIN [dbo].[Claim] ON (Claim.Id = ContentItem.Id);
Here's one of my many iterations of LINQ queries (which is not returning the desired result).
var queryRetailers = contentItemModel
.Where(contentItem => contentItem.Type == ContentTypeEnum.Retailer)
.OrderByDescending(o => o.mtime).Skip(skip).Take(take).Select(o => new { Id = o.Id });
var queryBrands = contentItemModel
.Where(contentItem => contentItem.Type == ContentTypeEnum.Brand)
.OrderByDescending(o => o.mtime).Skip(skip).Take(take).Select(o => new { Id = o.Id });
var queryProducts = contentItemModel
.Where(contentItem => contentItem.Type == ContentTypeEnum.Product)
.OrderByDescending(o => o.mtime).Skip(skip).Take(take).Select(o => new { Id = o.Id });
var queryCertifications = contentItemModel
.Where(contentItem => contentItem.Type == ContentTypeEnum.Certification)
.OrderByDescending(o => o.mtime).Skip(skip).Take(take).Select(o => new { Id = o.Id });
var queryClaims = contentItemModel
.Where(contentItem => contentItem.Type == ContentTypeEnum.Claim)
.OrderByDescending(o => o.mtime).Skip(skip).Take(take).Select(o => new { Id = o.Id });
var query = from contentItem in
queryRetailers
.Concat(queryBrands)
.Concat(queryProducts)
.Concat(queryCertifications)
.Concat(queryClaims)
join item in context.Retailer on contentItem.Id equals item.Id into retailerGroup
from retailer in retailerGroup.DefaultIfEmpty(null)
join item in context.Brand on contentItem.Id equals item.Id into brandGroup
from brand in brandGroup.DefaultIfEmpty(null)
join item in context.Product on contentItem.Id equals item.Id into productGroup
from product in productGroup.DefaultIfEmpty(null)
join item in context.Certification on contentItem.Id equals item.Id into certificationGroup
from certification in certificationGroup.DefaultIfEmpty(null)
join item in context.Claim on contentItem.Id equals item.Id into claimGroup
from claim in claimGroup.DefaultIfEmpty(null)
select new
{
contentItem,
retailer,
brand,
product,
certification,
claim
};
var results = query.ToList();
This query returns SQL that essentially "nests" my UNION ALL statements, and the server returns all rows from the database.
SELECT
[Distinct4].[C1] AS [C1],
[Distinct4].[C2] AS [C2],
[Extent6].[Id] AS [Id],
[Extent6].[RowVersion] AS [RowVersion],
[Extent6].[ctime] AS [ctime],
[Extent6].[mtime] AS [mtime],
[Extent7].[Id] AS [Id1],
[Extent7].[Recommended] AS [Recommended],
[Extent7].[RowVersion] AS [RowVersion1],
[Extent7].[ctime] AS [ctime1],
[Extent7].[mtime] AS [mtime1],
[Extent8].[Id] AS [Id2],
[Extent8].[OverrideGrade] AS [OverrideGrade],
[Extent8].[PlantBased] AS [PlantBased],
[Extent8].[Recommended] AS [Recommended1],
[Extent8].[RowVersion] AS [RowVersion2],
[Extent8].[ctime] AS [ctime2],
[Extent8].[mtime] AS [mtime2],
[Extent8].[Brand_Id] AS [Brand_Id],
[Extent8].[Grade_Name] AS [Grade_Name],
[Extent8].[Grade_Value] AS [Grade_Value],
[Extent9].[Id] AS [Id3],
[Extent9].[RowVersion] AS [RowVersion3],
[Extent9].[ctime] AS [ctime3],
[Extent9].[mtime] AS [mtime3],
[Extent9].[Grade_Name] AS [Grade_Name1],
[Extent9].[Grade_Value] AS [Grade_Value1],
[Extent10].[Id] AS [Id4],
[Extent10].[RowVersion] AS [RowVersion4],
[Extent10].[ctime] AS [ctime4],
[Extent10].[mtime] AS [mtime4],
[Extent10].[Grade_Name] AS [Grade_Name2],
[Extent10].[Grade_Value] AS [Grade_Value2]
FROM (SELECT DISTINCT
[UnionAll4].[C1] AS [C1],
[UnionAll4].[C2] AS [C2]
FROM (SELECT
[Distinct3].[C1] AS [C1],
[Distinct3].[C2] AS [C2]
FROM ( SELECT DISTINCT
[UnionAll3].[C1] AS [C1],
[UnionAll3].[C2] AS [C2]
FROM (SELECT
[Distinct2].[C1] AS [C1],
[Distinct2].[C2] AS [C2]
FROM ( SELECT DISTINCT
[UnionAll2].[C1] AS [C1],
[UnionAll2].[C2] AS [C2]
FROM (SELECT
[Distinct1].[C1] AS [C1],
[Distinct1].[C2] AS [C2]
FROM ( SELECT DISTINCT
[UnionAll1].[C1] AS [C1],
[UnionAll1].[Id] AS [C2]
FROM (SELECT TOP (1000)
[Project1].[C1] AS [C1],
[Project1].[Id] AS [Id]
FROM ( SELECT [Project1].[Id] AS [Id], [Project1].[mtime] AS [mtime], [Project1].[C1] AS [C1], row_number() OVER (ORDER BY [Project1].[mtime] DESC) AS [row_number]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[mtime] AS [mtime],
1 AS [C1]
FROM [dbo].[ContentItem] AS [Extent1]
WHERE 0 = CAST( [Extent1].[Type] AS int)
) AS [Project1]
) AS [Project1]
WHERE [Project1].[row_number] > 0
ORDER BY [Project1].[mtime] DESC
UNION ALL
SELECT TOP (1000)
[Project3].[C1] AS [C1],
[Project3].[Id] AS [Id]
FROM ( SELECT [Project3].[Id] AS [Id], [Project3].[mtime] AS [mtime], [Project3].[C1] AS [C1], row_number() OVER (ORDER BY [Project3].[mtime] DESC) AS [row_number]
FROM ( SELECT
[Extent2].[Id] AS [Id],
[Extent2].[mtime] AS [mtime],
1 AS [C1]
FROM [dbo].[ContentItem] AS [Extent2]
WHERE 1 = CAST( [Extent2].[Type] AS int)
) AS [Project3]
) AS [Project3]
WHERE [Project3].[row_number] > 0
ORDER BY [Project3].[mtime] DESC) AS [UnionAll1]
) AS [Distinct1]
UNION ALL
SELECT TOP (1000)
[Project7].[C1] AS [C1],
[Project7].[Id] AS [Id]
FROM ( SELECT [Project7].[Id] AS [Id], [Project7].[mtime] AS [mtime], [Project7].[C1] AS [C1], row_number() OVER (ORDER BY [Project7].[mtime] DESC) AS [row_number]
FROM ( SELECT
[Extent3].[Id] AS [Id],
[Extent3].[mtime] AS [mtime],
1 AS [C1]
FROM [dbo].[ContentItem] AS [Extent3]
WHERE 2 = CAST( [Extent3].[Type] AS int)
) AS [Project7]
) AS [Project7]
WHERE [Project7].[row_number] > 0
ORDER BY [Project7].[mtime] DESC) AS [UnionAll2]
) AS [Distinct2]
UNION ALL
SELECT TOP (1000)
[Project11].[C1] AS [C1],
[Project11].[Id] AS [Id]
FROM ( SELECT [Project11].[Id] AS [Id], [Project11].[mtime] AS [mtime], [Project11].[C1] AS [C1], row_number() OVER (ORDER BY [Project11].[mtime] DESC) AS [row_number]
FROM ( SELECT
[Extent4].[Id] AS [Id],
[Extent4].[mtime] AS [mtime],
1 AS [C1]
FROM [dbo].[ContentItem] AS [Extent4]
WHERE 3 = CAST( [Extent4].[Type] AS int)
) AS [Project11]
) AS [Project11]
WHERE [Project11].[row_number] > 0
ORDER BY [Project11].[mtime] DESC) AS [UnionAll3]
) AS [Distinct3]
UNION ALL
SELECT TOP (1000)
[Project15].[C1] AS [C1],
[Project15].[Id] AS [Id]
FROM ( SELECT [Project15].[Id] AS [Id], [Project15].[mtime] AS [mtime], [Project15].[C1] AS [C1], row_number() OVER (ORDER BY [Project15].[mtime] DESC) AS [row_number]
FROM ( SELECT
[Extent5].[Id] AS [Id],
[Extent5].[mtime] AS [mtime],
1 AS [C1]
FROM [dbo].[ContentItem] AS [Extent5]
WHERE 4 = CAST( [Extent5].[Type] AS int)
) AS [Project15]
) AS [Project15]
WHERE [Project15].[row_number] > 0
ORDER BY [Project15].[mtime] DESC) AS [UnionAll4] ) AS [Distinct4]
LEFT OUTER JOIN [dbo].[Retailer] AS [Extent6] ON [Distinct4].[C2] = [Extent6].[Id]
LEFT OUTER JOIN [dbo].[Brand] AS [Extent7] ON [Distinct4].[C2] = [Extent7].[Id]
LEFT OUTER JOIN [dbo].[Product] AS [Extent8] ON [Distinct4].[C2] = [Extent8].[Id]
LEFT OUTER JOIN [dbo].[Certification] AS [Extent9] ON [Distinct4].[C2] = [Extent9].[Id]
LEFT OUTER JOIN [dbo].[Claim] AS [Extent10] ON [Distinct4].[C2] = [Extent10].[Id]
So my overall questions are:
1) Is there a simpler SQL query I can execute to get the same results? I know that T-SQL doesn't support offsets per table in a subquery, hence the subquery wrapping.
2) If there isn't, what am I doing wrong in my LINQ query? Is this even possible with LINQ?
I wanted to add the SQL from #radar here all nice and formatted. It at least appears to be an elegant solution to avoid the sub-subqueries, and still accomplishes the offset/fetch.
SELECT *
FROM (SELECT
[ContentItem].*,
row_number() OVER ( PARTITION BY Type ORDER BY ContentItem.mtime ) as rn
FROM [dbo].[ContentItem]
LEFT JOIN [dbo].[Retailer] ON (Retailer.Id = ContentItem.Id)
LEFT JOIN [dbo].[Brand] ON (Brand.Id = ContentItem.Id)
LEFT JOIN [dbo].[Product] ON (Product.Id = ContentItem.Id)
LEFT JOIN [dbo].[Certification] ON (Certification.Id = ContentItem.Id)
LEFT JOIN [dbo].[Claim] ON (Claim.Id = ContentItem.Id)
) as x
WHERE x.rn >= a AND x.rn <= b;
a is the lower threshold (offset) and b is the upper threshold (fetch-ish). The only catch is that b now equals fetch + a instead of just fetch. The first set of results would be WHERE x.rn >= 0 AND x.rn <= 6, the second set WHERE x.rn >= 6 AND x.rn <= 12, third WHERE x.rn >= 12 AND x.rn <= 18, and so on.
As you are looking simpler SQL, you can use row_number analytic function, which would be faster
You need to try and see as there are many left joins and also proper index need to exists in these tables.
select *
from (
select *, row_number() over ( partition by Type order by ContentItem.mtime ) as rn
from [dbo].[ContentItem]
LEFT JOIN [dbo].[Retailer] ON (Retailer.Id = ContentItem.Id)
LEFT JOIN [dbo].[Brand] ON (Brand.Id = ContentItem.Id)
LEFT JOIN [dbo].[Product] ON (Product.Id = ContentItem.Id)
LEFT JOIN [dbo].[Certification] ON (Certification.Id = ContentItem.Id)
LEFT JOIN [dbo].[Claim] ON (Claim.Id = ContentItem.Id);
)
where rn <= 6
Well, it appears that I'm an idiot. That TOP(1000) call should have tipped me off. I assumed that my take variable was set to 6 but it was, in fact, set to 1000. Turns out my giant LINQ query works as expected, but the nested UNION ALL statements threw me off.
Still, I'm going to investigate #radar's answer further. It's hard to argue with better performance.
I know it's ain't gonna be easy but I'm stuck on this and can't move on.
I have this linq
var resourceItems = queryable
.Select(ri => new ResourceItemDto
{
Id = ri.Id,
CreationDate = ri.CreationDate,
ParentId = ri.FolderId,
Name = ri.Name,
Type = ri.ResourceType,
Url = ri.Url,
Size = ri.Size,
MediaAssetUuid = ri.MediaAssetUuid,
Blob = ri.Blob,
Container = ri.Container,
GroupId = ri.GroupId,
Status = (ResourceItemStatus) ri.Status,
Progress =
ri.EncodingJobs.SelectMany(j => j.EncodingTasks).Any()
? (ri.EncodingJobs.SelectMany(j => j.EncodingTasks).Sum(t => (decimal?) t.Progress)/
ri.EncodingJobs.SelectMany(j => j.EncodingTasks).Count() ?? 0M)
: 0M,
Uuid = ri.Uuid,
CreatedBy =
new UserDto
{
Id = ri.User.Id,
UserName = ri.User.UserName,
FirstName = ri.User.FirstName,
LastName = ri.User.LastName
}
});
And now the task is to move this into a SP and I don't want to take the sql generated by the EF, it's clumsy and machine-generated.
I ended up having this:
SELECT
ri.Id
,ri.CreationDate
,ri.FolderId
,ri.Name
,ri.ResourceType
,ri.Url
,ri.Size
,ri.MediaAssetUuid
,ri.Blob
,ri.Container
,ri.GroupId
--, (sql_expression) AS Progress
,ri.Uuid
,u.Id AS UserId
,u.UserName
,u.FirstName
,u.LastName
FROM ResourceItem ri
INNER JOIN ResourceItemsTree rit ON ri.FolderId = rit.Id
INNER JOIN [User] u ON u.Id = ri.CreatedBy
WHERE
ri.IsDeleted = CAST(0 as BIT)
Now my problem is that Progress column calculation which includes a few repeating SelectMany statements and I don't know how to do with this.
Any help is really appreciated, guys.
There's a EncodingJobs table having a FK ResourceItemId (0 to many) to the resourceItem table, and there's another table EncodingTask with a FK EncodingJobId (the same 0 to many).
This is what EF generates:
SELECT
[Project4].[Id] AS [Id],
[Project4].[CreationDate] AS [CreationDate],
[Project4].[FolderId] AS [FolderId],
[Project4].[Name] AS [Name],
[Project4].[ResourceType] AS [ResourceType],
[Project4].[Url] AS [Url],
[Project4].[Size] AS [Size],
[Project4].[MediaAssetUuid] AS [MediaAssetUuid],
[Project4].[Blob] AS [Blob],
[Project4].[Container] AS [Container],
[Project4].[GroupId] AS [GroupId],
[Project4].[Status] AS [Status],
CASE WHEN ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[EncodingJob] AS [Extent12]
INNER JOIN [dbo].[EncodingTask] AS [Extent13] ON [Extent12].[Id] = [Extent13].[JobId]
WHERE [Project4].[Id] = [Extent12].[ResourceItemId]
)) THEN CASE WHEN ([Project4].[C1] / CAST( [Project4].[C2] AS decimal(19,0)) IS NULL) THEN cast(0 as decimal(18)) ELSE [Project4].[C3] / CAST( [Project4].[C4] AS decimal(19,0)) END ELSE cast(0 as decimal(18)) END AS [C1],
[Project4].[Uuid] AS [Uuid],
[Project4].[CreatedBy] AS [CreatedBy],
[Project4].[UserName] AS [UserName],
[Project4].[FirstName] AS [FirstName],
[Project4].[LastName] AS [LastName]
FROM ( SELECT
[Project3].[Id] AS [Id],
[Project3].[FolderId] AS [FolderId],
[Project3].[Name] AS [Name],
[Project3].[ResourceType] AS [ResourceType],
[Project3].[Url] AS [Url],
[Project3].[Size] AS [Size],
[Project3].[MediaAssetUuid] AS [MediaAssetUuid],
[Project3].[Status] AS [Status],
[Project3].[CreationDate] AS [CreationDate],
[Project3].[GroupId] AS [GroupId],
[Project3].[Container] AS [Container],
[Project3].[Blob] AS [Blob],
[Project3].[Uuid] AS [Uuid],
[Project3].[CreatedBy] AS [CreatedBy],
[Project3].[UserName] AS [UserName],
[Project3].[FirstName] AS [FirstName],
[Project3].[LastName] AS [LastName],
[Project3].[C1] AS [C1],
[Project3].[C2] AS [C2],
[Project3].[C3] AS [C3],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[EncodingJob] AS [Extent10]
INNER JOIN [dbo].[EncodingTask] AS [Extent11] ON [Extent10].[Id] = [Extent11].[JobId]
WHERE [Project3].[Id] = [Extent10].[ResourceItemId]) AS [C4]
FROM ( SELECT
[Project2].[Id] AS [Id],
[Project2].[FolderId] AS [FolderId],
[Project2].[Name] AS [Name],
[Project2].[ResourceType] AS [ResourceType],
[Project2].[Url] AS [Url],
[Project2].[Size] AS [Size],
[Project2].[MediaAssetUuid] AS [MediaAssetUuid],
[Project2].[Status] AS [Status],
[Project2].[CreationDate] AS [CreationDate],
[Project2].[GroupId] AS [GroupId],
[Project2].[Container] AS [Container],
[Project2].[Blob] AS [Blob],
[Project2].[Uuid] AS [Uuid],
[Project2].[CreatedBy] AS [CreatedBy],
[Project2].[UserName] AS [UserName],
[Project2].[FirstName] AS [FirstName],
[Project2].[LastName] AS [LastName],
[Project2].[C1] AS [C1],
[Project2].[C2] AS [C2],
(SELECT
SUM([Extent9].[Progress]) AS [A1]
FROM [dbo].[EncodingJob] AS [Extent8]
INNER JOIN [dbo].[EncodingTask] AS [Extent9] ON [Extent8].[Id] = [Extent9].[JobId]
WHERE [Project2].[Id] = [Extent8].[ResourceItemId]) AS [C3]
FROM ( SELECT
[Project1].[Id] AS [Id],
[Project1].[FolderId] AS [FolderId],
[Project1].[Name] AS [Name],
[Project1].[ResourceType] AS [ResourceType],
[Project1].[Url] AS [Url],
[Project1].[Size] AS [Size],
[Project1].[MediaAssetUuid] AS [MediaAssetUuid],
[Project1].[Status] AS [Status],
[Project1].[CreationDate] AS [CreationDate],
[Project1].[GroupId] AS [GroupId],
[Project1].[Container] AS [Container],
[Project1].[Blob] AS [Blob],
[Project1].[Uuid] AS [Uuid],
[Project1].[CreatedBy] AS [CreatedBy],
[Project1].[UserName] AS [UserName],
[Project1].[FirstName] AS [FirstName],
[Project1].[LastName] AS [LastName],
[Project1].[C1] AS [C1],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[EncodingJob] AS [Extent6]
INNER JOIN [dbo].[EncodingTask] AS [Extent7] ON [Extent6].[Id] = [Extent7].[JobId]
WHERE [Project1].[Id] = [Extent6].[ResourceItemId]) AS [C2]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FolderId] AS [FolderId],
[Extent1].[Name] AS [Name],
[Extent1].[ResourceType] AS [ResourceType],
[Extent1].[Url] AS [Url],
[Extent1].[Size] AS [Size],
[Extent1].[MediaAssetUuid] AS [MediaAssetUuid],
[Extent1].[Status] AS [Status],
[Extent1].[CreationDate] AS [CreationDate],
[Extent1].[GroupId] AS [GroupId],
[Extent1].[Container] AS [Container],
[Extent1].[Blob] AS [Blob],
[Extent1].[Uuid] AS [Uuid],
[Extent1].[CreatedBy] AS [CreatedBy],
[Extent2].[UserName] AS [UserName],
[Extent3].[FirstName] AS [FirstName],
[Extent3].[LastName] AS [LastName],
(SELECT
SUM([Extent5].[Progress]) AS [A1]
FROM [dbo].[EncodingJob] AS [Extent4]
INNER JOIN [dbo].[EncodingTask] AS [Extent5] ON [Extent4].[Id] = [Extent5].[JobId]
WHERE [Extent1].[Id] = [Extent4].[ResourceItemId]) AS [C1]
FROM [dbo].[ResourceItem] AS [Extent1]
INNER JOIN [dbo].[User] AS [Extent2] ON [Extent1].[CreatedBy] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[User] AS [Extent3] ON [Extent1].[CreatedBy] = [Extent3].[Id]
WHERE ([Extent1].[IsDeleted] <> cast(1 as bit)) AND ([Extent1].[FolderId] = #p__linq__0)
) AS [Project1]
) AS [Project2]
) AS [Project3]
) AS [Project4]
you just need to think what you are looking for.
In this case its the total of the progress / count, grouped per resourceItem.
The following should be about right, but the IDs might need correcting!
This uses a common table expression (SQL Server) but could easily be rewritten to a subquery
;WITH prog AS
(
SELECT
ej.ResourceItemId,
SUM(et.Progress) / COUNT(*) AS totalProg
FROM EncodingJobs ej
JOIN EncodingTasks et ON ej.Id = et.EncodingJobId
GROUP BY
ej.ResourceItemId
)
SELECT
ri.Id
,ri.CreationDate
,ri.FolderId
,ri.Name
,ri.ResourceType
,ri.Url
,ri.Size
,ri.MediaAssetUuid
,ri.Blob
,ri.Container
,ri.GroupId
,ISNULL(prog.totalProg, 0) AS Progress
,ri.Uuid
,u.Id AS UserId
,u.UserName
,u.FirstName
,u.LastName
FROM ResourceItem ri
INNER JOIN ResourceItemsTree rit ON ri.FolderId = rit.Id
INNER JOIN [User] u ON u.Id = ri.CreatedBy
LEFT JOIN prog ON ri.Id = prog.ResourceItemId
WHERE
ri.IsDeleted = CAST(0 as BIT)
Well this should be something like that.
Cast the count to decimal if Progress is an integer, to avoid integer division.If not, you can avoid the cast
SELECT
ri.Id
,ri.CreationDate
,ri.FolderId
,ri.Name
,ri.ResourceType
,ri.Url
,ri.Size
,ri.MediaAssetUuid
,ri.Blob
,ri.Container
,ri.GroupId
coalesce(sum(et.Progress) / cast(count(*) as decimal(18,2)), 0) AS Progress
,ri.Uuid
,u.Id AS UserId
,u.UserName
,u.FirstName
,u.LastName
FROM ResourceItem ri
INNER JOIN ResourceItemsTree rit ON ri.FolderId = rit.Id
INNER JOIN [User] u ON u.Id = ri.CreatedBy
LEFT JOIN EncodingJob ej on ej.ResourceItemId= ri.Id
LEFT JOIN EncodingTask et on et.JobId = ej.Id
WHERE
ri.IsDeleted = 0
group by
ri.Id
,ri.CreationDate
,ri.FolderId
,ri.Name
,ri.ResourceType
,ri.Url
,ri.Size
,ri.MediaAssetUuid
,ri.Blob
,ri.Container
,ri.GroupId
,ri.Uuid
,u.Id AS UserId
,u.UserName
,u.FirstName
,u.LastName
You can attach SQL Server Profiler to my database and run the application. SQL Server Profiler will capture the SQL that is being run on the database. You can then use that SQL as a starting point for your stored procedure.
SQL Server Profiler Tutorial