Sum subquery Oracle - sql

I'm doing a SQL query and I'm trying to sum the result of my subquery, but without success. The command does not execute
Can someone help me?
The query I'm doing is:
SELECT cm.course_id,cm.course_name, sum (select max(SCORE) from
ATTEMPT where GRADEBOOK_GRADE_PK1 = GG.PK1 group by 1)
FROM gradebook_main gm
JOIN course_main cm ON cm.pk1 = gm.crsmain_pk1
JOIN gradebook_grade gg ON gm.pk1 = gg.gradebook_main_pk1
JOIN course_users cu ON cu.pk1 = gg.course_users_pk1
JOIN users u ON u.pk1 = cu.users_pk1
WHERE U.user_id = '1616894251'
group by cm.course_id, cm.course_name
Thanks!

I have tried build you subselect as joined table ..hopre the group by column is GRADEBOOK_GRADE_PK1
SELECT
cm.course_id
, cm.course_name
, sum ( t.max_score
)
FROM gradebook_main gm
JOIN course_main cm ON cm.pk1 = gm.crsmain_pk1
JOIN gradebook_grade gg ON gm.pk1 = gg.gradebook_main_pk1
JOIN course_users cu ON cu.pk1 = gg.course_users_pk1
JOIN users u ON u.pk1 = cu.users_pk1
JOIN (
select GRADEBOOK_GRADE_PK1, max(SCORE) max_score
from ATTEMPT
group by GRADEBOOK_GRADE_PK1
) t on t.GRADEBOOK_GRADE_PK1 = GG.PK1
WHERE U.user_id = '1616894251'
group by cm.course_id, cm.course_name

Related

Sum from the different tables Sql server

I have couple of tables which stores amount and I want to group by and get sum - reason for the mutiple tables are nhibernate descriminators.
I am using Union all and works but query is very big.
I am using following query
SELECT CustomerAccountNumber,
vc.CustomerName,
SUM(PermAmount) AS PermAmount,
SUM(FreetextAmount) AS FreetextAmount,
(SUM(PermAmount) + SUM(FreetextAmount)) AS TotalAmountByCustomer
FROM
(
SELECT pp.CustomerAccountNumber,
pl.Amount AS PermAmount,
0 AS FreetextAmount
FROM dbo.PermanentPlacementTransactionLine pl
INNER JOIN dbo.TransactionLine tl ON pl.TransactionLineId = tl.Id
INNER JOIN dbo.PermanentPlacement pp ON pl.PermanentPlacementId = pp.Id
WHERE tl.CurrentStatus = 1
GROUP BY pp.CustomerAccountNumber,
pl.Amount,
tl.Id
UNION ALL
SELECT ft.CustomerAccountNumber,
0 AS PermAmount,
ft.Amount AS FreetextAmount
FROM dbo.FreeTextTransactionLine fttl
INNER JOIN dbo.TransactionLine tl ON fttl.TransactionLineId = tl.Id
INNER JOIN dbo.[FreeText] ft ON fttl.FreeTextId = ft.Id
WHERE tl.CurrentStatus = 1
GROUP BY ft.CustomerAccountNumber,
ft.Amount,
tl.Id
) WIPSummary
INNER JOIN dbo.vw_Customer vc ON WIPSummary.CustomerAccountNumber = vc.CustomerAccount
GROUP BY CustomerAccountNumber,
vc.CustomerName;
is there any elegant way of displaying amount in separate columns ?
I can use partition by if it was same table and want to display row by row.
Try these query, is easy to understand and probably faster than yours.
I assume that the values are unique in your view
WITH cte_a
AS (SELECT pp.customeraccountnumber
,Sum(pl.amount) AS PermAmount
,0 AS FreetextAmount
FROM dbo.permanentplacementtransactionline pl
INNER JOIN dbo.transactionline tl
ON pl.transactionlineid = tl.id
INNER JOIN dbo.permanentplacement pp
ON pl.permanentplacementid = pp.id
WHERE tl.currentstatus = 1
GROUP BY pp.customeraccountnumber),
cte_b
AS (SELECT ft.customeraccountnumber
,0 AS PermAmount
,Sum(ft.amount) AS FreetextAmount
FROM dbo.freetexttransactionline fttl
INNER JOIN dbo.transactionline tl
ON fttl.transactionlineid = tl.id
INNER JOIN dbo.[freetext] ft
ON fttl.freetextid = ft.id
WHERE tl.currentstatus = 1
GROUP BY ft.customeraccountnumber)
SELECT vc.customeraccountnumber
,vc.customername
,Isnull(A.permamount, 0) AS PermAmount
,Isnull(B.freetextamount, 0) AS FreetextAmount
,Isnull(A.permamount, 0)
+ Isnull(B.freetextamount, 0) AS TotalAmountByCustomer
FROM dbo.vw_customer vc
LEFT JOIN cte_a a
ON vc.customeraccount = A.customeraccountnumber
LEFT JOIN cte_b b
ON vc.customeraccount = A.customeraccountnumber
if no table structures and sample data, that is the best I can do to help you.

Get total count using a window function

Hey all this is the query I have so far:
WITH LIMIT AS
(SELECT
U.userID
,U.username
,U.fname
,U.mname
,U.lname
,U.email
,U.active
,S.sName
,S.sID
,T.[value]
,T.trackingNumberID
,SU.primaryLocation
,row_number() OVER (ORDER BY U.userid) AS RN
,COUNT(*) OVER (ORDER BY U.userid) AS CNT
,UR.roleID
FROM
[---].[dbo].[tblUsers] AS U
LEFT OUTER JOIN [---].[dbo].[tblTrackingNumbers] AS T
ON T.userID = U.userID
LEFT OUTER JOIN [---].[dbo].[tblSU] AS SU
ON U.userID = SU.userID
LEFT OUTER JOIN [---].[dbo].[tblS] AS S
ON SU.sID = S.sID
LEFT OUTER JOIN [---].[dbo].[tblUserRoles] AS UR
ON UR.userID = U.userID
LEFT OUTER JOIN [---].[dbo].[tblRoles] AS R
ON UR.roleID = R.roleID
WHERE
U.active = 1
AND
SU.primaryLocation = 1
AND
SU.active = 1
AND
U.orgID = 1
AND
S.ID = 35
AND U.userID IN (SELECT userID
FROM [---].[dbo].[tblSU] AS SU
INNER JOIN [].[dbo].[tblS] AS S
ON S.sID = SU.sID
WHERE
SU.active = 1
AND
S.sID = 35)
) SELECT * FROM LIMIT WHERE RN Between 0 AND 10000
As you can see by the query above I am trying COUNT(*) OVER (ORDER BY U.userid) AS CNT which gives me the same count as RN.
What I need is the total amount of records this would be bringing back (842 rows).
COUNT(*) OVER (ORDER BY U.userid) AS CNT calulates a "running count" - the count until "that" row. If you want to count all rows in the complete result, use the window function without the order by
COUNT(*) OVER () AS CNT
this might sound cuckoo, but i found with large tables you get better performance if you select the count into a variable and then select your records and just add the variable. something with the count(*) over() causes bad performance when tables get too large.
DECLARE #RecordCount INT
SELECT #RecordCount = COUNT(*)
FROM [---].[dbo].[tblUsers] AS U
LEFT OUTER JOIN [---].[dbo].[tblTrackingNumbers] AS T ON T.userID = U.userID
LEFT OUTER JOIN [---].[dbo].[tblSU] AS SU ON U.userID = SU.userID
LEFT OUTER JOIN [---].[dbo].[tblS] AS S ON SU.sID = S.sID
LEFT OUTER JOIN [---].[dbo].[tblUserRoles] AS UR ON UR.userID = U.userID
LEFT OUTER JOIN [---].[dbo].[tblRoles] AS R ON UR.roleID = R.roleID
WHERE U.active = 1
AND SU.primaryLocation = 1
AND SU.active = 1
AND U.orgID = 1
AND S.ID = 35
AND U.userID IN (SELECT userID
FROM [---].[dbo].[tblSU] AS SU
INNER JOIN [].[dbo].[tblS] AS S ON S.sID = SU.sID
WHERE SU.active = 1
AND S.sID = 35)
SELECT U.userID,
U.username,
U.fname,
U.mname,
U.lname,
U.email,
U.active,
S.sName,
S.sID,
T.[value],
T.trackingNumberID,
SU.primaryLocation,
#RecordCount AS CNT,
UR.roleID
FROM [---].[dbo].[tblUsers] AS U
LEFT OUTER JOIN [---].[dbo].[tblTrackingNumbers] AS T ON T.userID = U.userID
LEFT OUTER JOIN [---].[dbo].[tblSU] AS SU ON U.userID = SU.userID
LEFT OUTER JOIN [---].[dbo].[tblS] AS S ON SU.sID = S.sID
LEFT OUTER JOIN [---].[dbo].[tblUserRoles] AS UR ON UR.userID = U.userID
LEFT OUTER JOIN [---].[dbo].[tblRoles] AS R ON UR.roleID = R.roleID
WHERE U.active = 1
AND SU.primaryLocation = 1
AND SU.active = 1
AND U.orgID = 1
AND S.ID = 35
AND U.userID IN (SELECT userID
FROM [---].[dbo].[tblSU] AS SU
INNER JOIN [].[dbo].[tblS] AS S ON S.sID = SU.sID
WHERE SU.active = 1
AND S.sID = 35)
ORDER BY U.userID
OFFSET 0 ROWS FETCH NEXT 10000 ROWS ONLY

How to retrieve count of records in SELECT statement

I am trying to retrieve the right count of records to mitigate an issue I am having. The below query returns 327 records from my database:
SELECT DISTINCT COUNT(at.someid) AS CountOfStudentsInTable FROM tblJobSkillAssessment AS at
INNER JOIN tblJobSkills j ON j.jobskillid = at.skillid
LEFT JOIN tblStudentPersonal sp ON sp.someid2 = at.someid
INNER JOIN tblStudentSchool ss ON ss.monsterid = at.someid
INNER JOIN tblSchools s ON s.schoolid = ss.schoolid
INNER JOIN tblSchoolDistricts sd ON sd.schoolid = s.schoolid
INNER JOIN tblDistricts d ON d.districtid = sd.districtid
INNER JOIN tblCountySchools cs ON cs.schoolid = s.schoolid
INNER JOIN tblCounties cty ON cty.countyid = cs.countyid
INNER JOIN tblRegionUserRegionGroups rurg ON rurg.districtid = d.districtid
INNER JOIN tblGroups g ON g.groupid = rurg.groupid
WHERE ss.graduationyear IN (SELECT Items FROM FN_Split(#gradyears, ',')) AND sp.optin = 'Yes' AND g.groupname = #groupname
Where I run into trouble is trying to reconcile that with the below query. One is for showing just a count of all the particular students the other is showing pertinent information for a set of students as needed but the total needs to be the same and it is not. The below query return 333 students - the reason is because the school the student goes to is in two separate counties and it counts that student twice. I can't figure out how to fix this.
SELECT DISTINCT #TableName AS TableName, d.district AS LocationName, cty.county AS County, COUNT(DISTINCT cc.monsterid) AS CountOfStudents, d.IRN AS IRN FROM tblJobSkillAssessment AS cc
INNER JOIN tblJobSkills AS c ON c.jobskillid = cc.skillid
INNER JOIN tblStudentPersonal sp ON sp.monsterid = cc.monsterid
INNER JOIN tblStudentSchool ss ON ss.monsterid = cc.monsterid
INNER JOIN tblSchools s ON s.schoolid = ss.schoolid
INNER JOIN tblSchoolDistricts sd ON sd.schoolid = s.schoolid
INNER JOIN tblDistricts d ON d.districtid = sd.districtid
INNER JOIN tblCountySchools cs ON cs.schoolid = s.schoolid
INNER JOIN tblCounties cty ON cty.countyid = cs.countyid
INNER JOIN tblRegionUserRegionGroups rurg ON rurg.districtid = d.districtid
INNER JOIN tblGroups g ON g.groupid = rurg.groupid
WHERE ss.graduationyear IN (SELECT Items FROM FN_Split(#gradyears, ',')) AND sp.optin = 'Yes' AND g.groupname = #groupname
GROUP BY cty.county, d.IRN, d.district
ORDER BY LocationName ASC
If you just want the count, then perhaps count(distinct) will solve the problem:
select count(distinct at.someid)
I don't see what at.someid refers to, so perhaps:
select count(distinct cc.monsterid)

SQL Server : JOIN query

I'm newbie in SQL Server and I need some help with SQL Server and JOIN method.
My code is:
SELECT TOP 1000
p.value AS userposition,
p2.value AS usercell,
t.id
FROM
[es] t
JOIN
[user] u ON t.user_uid = u.uid
JOIN
[user] su ON u.superior_uid = su.uid
JOIN
[user_params] up ON t.user_uid = up.user_uid
LEFT JOIN
[params] p ON up.param_id = p.id AND p.name_id = 1
JOIN
[user_params] up2 ON t.user_uid = up2.user_uid
LEFT JOIN
[params] p2 ON up2.param_id = p2.id AND p.name_id = 2
but it returns duplicated records. I want them just as many as rows in [es] table. In MySQL I would use GROUP BY t.id, but in SQL Server that method doesn't work.
Thanks in advance.
EDIT (clarification):
Thank you for your replies. Maybe I should describe my tables structure and what I need to display.
Table [ES]
[id],[user_uid],[more_data]
Table [User]
[uid],[superior_uid],[more_data]
Table [UserParams]
[id],[user_uid],[param_id]
Table [Params]
[id],[param_id],[value]
Now what I need is to get all records from [ES] add user data from [User] add his superior data on [User][superior_uid] which is also an [User] record, add [Params] with [Params][name_id] = 1 as value1 AND add [Params] with [Params][name_id] = 2 as value2 ... through [UserParams] if exists.
I think the problem is with JOIN or GROUP BY. [ES] records with users has no [UserParams] are shown only once, but those with [UserParams] are doubled.I tried LEFT OUTER JOIN but it doesn't work. :(
How about
SELECT DISTINCT TOP 1000
p.value AS userposition,
p2.value AS usercell,
t.id
FROM [es] t
JOIN [user] u ON t.user_uid = u.uid
JOIN [user] su ON u.superior_uid = su.uid
JOIN [user_params] up ON t.user_uid = up.user_uid
LEFT JOIN [params] p ON up.param_id = p.id AND p.name_id = 1
JOIN [user_params] up2 ON t.user_uid = up2.user_uid
LEFT JOIN [params] p2 ON up2.param_id = p2.id AND p.name_id = 2
ORDER BY (whichever rows that you want it to be ordered by) ?
all of your columns need to be in the group by, or part of an aggregate function
p.value AS userposition, #group by or agg func
p2.value AS usercell, #group by or agg func
t.id #group by
Wouldnt be certain without knowing what p.value and p2.value actually mean
Not to sure about the joins but I guess you know what you doing, to select distinct row you can use row_number() function as below
SELECT userposition
,usercell
,id
FROM (
SELECT TOP 1000
p.value AS userposition
,p2.value AS usercell
,t.id
,ROW_NUMBER() OVER (PARTITION BY t.user_uid ORDER BY t.user_uid) rn
FROM [es] t
INNER JOIN [user] u ON t.user_uid = u.[uid]
INNER JOIN [user] su ON u.superior_uid = su.[uid]
INNER JOIN [user_params] up ON t.user_uid = up.user_uid
LEFT JOIN [params] p ON up.param_id = p.id AND p.name_id = 1
INNER JOIN [user_params] up2 ON t.user_uid = up2.user_uid
LEFT JOIN [params] p2 ON up2.param_id = p2.id AND p.name_id = 2
) A
WHERE A.rn = 1
You can get rid of the last 2 joins by combining them, use DISTINCT to not get repeated entries, and use ORDER BY to sort it.
SELECT DISTINCT TOP 1000
p.value AS userposition,
p2.value AS usercell,
t.id
FROM [es] t
JOIN [user] u ON t.user_uid = u.uid
JOIN [user] su ON u.superior_uid = su.uid
JOIN [user_params] up ON t.user_uid = up.user_uid
LEFT JOIN [params] p ON up.param_id = p.id AND (p.name_id = 1 OR p.name_id = 2)
ORDER BY t.id

sql group by clause error

This is the error
Msg 8120, Level 16, State 1, Procedure FollowingUpdates, Line 10
Column 'TopicsComplete.TopicCreationDate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
This is after adding these 2 lines, I need to count a separate table rows (the amount of rows not the count of the topicid) and include in result any ideas? thanks
,COUNT(DISTINCT MC.topicid) AS NewMessagesCount
LEFT OUTER JOIN Messages AS MC ON MC.TopicId = T.TopicId AND MC.userid = #id
#id int = null
,#UserGroupId int = null
AS
SELECT
*
FROM
(SELECT
ROW_NUMBER()
OVER ( ORDER BY TopicOrder desc
, CASE WHEN M.MessageCreationDate > T.TopicCreationDate
THEN M.MessageCreationDate
ELSE T.TopicCreationDate
END desc )
AS RowNumber,
T.TopicId, T.TopicTitle, T.TopicShortName, T.TopicDescription, T.TopicCreationDate, T.TopicViews, T.TopicReplies, T.UserId, T.TopicTags, T.TopicIsClose, T.TopicOrder, T.LastMessageId, T.UserName, M.MessageCreationDate, T.ReadAccessGroupId, T.PostAccessGroupId, U.UserGroupId, U.UserPhoto, T.UserFullName ,M.UserId AS MessageUserId ,MU.UserName AS MessageUserName
,COUNT(DISTINCT MC.topicid) AS NewMessagesCount
FROM TopicsComplete AS T
LEFT OUTER JOIN Messages AS M ON M.TopicId = T.TopicId AND M.MessageId = T.LastMessageId AND M.Active = 1
LEFT OUTER JOIN Messages AS MC ON MC.TopicId = T.TopicId AND MC.userid = #id
INNER JOIN Users AS U ON U.UserId = T.UserId
LEFT JOIN Users MU ON MU.UserId = M.UserId
WHERE EXISTS
(SELECT * FROM TopicsComplete
LEFT OUTER JOIN Messages AS M ON M.TopicId = T.TopicId AND M.MessageId = T.LastMessageId AND M.Active = 1 INNER JOIN
topicfollows AS TF ON T.TopicId != TF.topicid INNER JOIN
Users AS U ON U.UserId = T.UserId LEFT OUTER JOIN
Users AS MU ON MU.UserId = M.UserId
WHERE (T.UserId = #id)
UNION SELECT * FROM TopicsComplete
LEFT OUTER JOIN Messages AS M ON M.TopicId = T.TopicId AND M.MessageId = T.LastMessageId AND M.Active = 1 INNER JOIN
topicfollows AS TF ON T.TopicId = TF.topicid INNER JOIN
Users AS U ON U.UserId = T.UserId LEFT JOIN
Users MU ON MU.UserId = M.UserId
WHERE (TF.userid = #id)
)
) T
When you have an aggregation function in the select, SQL Server quite reasonably assumes that you want to do an aggregation. All columns not in aggregation functions should then be in the group by clause.
In your case, you have COUNT(DISTINCT MC.topicid) AS NewMessagesCount in a select expression. All the other columns should be in the group by. There is no group by, but you get the error anyway, because one should be there.
You need to have any column not contained in an aggregate (max, min, count, sum, etc.) in the GROUP BY clause.