I'm using the following query, I need to show Grand Total count but it is throwing error like
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
SELECT
ISNULL(OQ.GroupID,'') GroupName,
CONVERT(VARCHAR, ISNULL(COUNT(CASE WHEN RequestStatusKey IN ( 1, 2 ) THEN OrderRecordID END), 0)) TotalRecord,
SUM(COUNT(CASE WHEN RequestStatusKey IN ( 1, 2 ) THEN OrderRecordID END)) AS GrandTotal
FROM dbo.tblDesk OQ
WHERE OQ.RequestStatusKey IN ( 1, 2 )
AND OQ.OrderTypeKey <> 1
AND OQ.GroupID IS NOT NULL
GROUP BY OQ.GroupID
ORDER BY OQ.GroupID
I just need to Grand total.
As the error message suggests, you can not use aggregate function inside another aggregate function.
For your query to achieve SUM of OrderRecordId when RequestStatusKey IN (1,2) you can use SUM without using COUNT like this:
SUM(CASE WHEN RequestStatusKey IN (1,2) THEN 1 ELSE 0 END) AS GrandTotal
However, as Tim suggested, since you have already used RequestStatusKey IN (1,2) in your WHERE clause you don't need to use conditional SUM. Just use COUNT without condition:
COUNT(OrderRecordId) AS GrandTotal
UPDATE:
Since you want to show sum of the all rows count in the same result, you can use ROLLUP for that:
SELECT
ISNULL(OQ.GroupID,'Grand Total') GroupName,
CONVERT(VARCHAR, COUNT(OrderRecordID)) TotalRecord
FROM tblDesk OQ
WHERE OQ.RequestStatusKey IN ( 1, 2 )
AND OQ.GroupID IS NOT NULL
GROUP BY ROLLUP (OQ.GroupID)
ORDER BY OQ.GroupID
See this SQLFiddle.
Related
I'm trying to make this query:
SELECT monthPosted,
sector,
COUNT(sumaAbas) as abasNum,
SUM(sumaAbas) as abas,
COUNT(usdAmount) AS totalNum,
SUM(usdAmount) AS total
FROM DatosSpend
WHERE negotiableProcGl='Y'
GROUP BY sector
The problem I'm getting here is that the COUNT(usdAmount) is counting all values also having a 0 in it.
How can I ignore the count of values=0?
Aggregate functions ignore nulls. You could use a case expression to convert 0s to nulls and thus skip them. E.g.:
SELECT monthPosted,
sector,
COUNT(sumaAbas) as abasNum,
SUM(sumaAbas) as abas,
COUNT(CASE usdAmount WHEN 0 THEN NULL ELSE 1 END) AS totalNum,
SUM(usdAmount) AS total
FROM DatosSpend
WHERE negotiableProcGl = 'Y'
GROUP BY sector
You can just simply exclude the 0 values in the WHERE clause:
WHERE negotiableProcGl='Y' AND value != 0
Where value is your column name
My table has columns such as ID,Perdium and Location so I want to calculate all the perdiums given to an employee and the perdium share given in NY. The issue which I am facing is that SQL Server engine is throwing as error stating that location column isnt present in the GROUP BY clause(as needed in my use-case).If I include the location in the Group By clause I always get NYPerdiumShare as 1 which is not what I am expecting. Is there any workaround to this?
WITH CTE_Employee AS
(
SELECT ID,
SUM(Perdium) AS TotalPerdium,
CASE WHEN Location='NY' THEN SUM(Perdium) ELSE NULL END AS NYPerdium FROM EmployeePerdium
GROUP BY ID
)
SELECT ID,
TotalPerdium,
NYPerdium/TotalPerdium AS NYPerdiumShare
FROM CTE_Employee
You can eliminate the need to group by on anything other than ID by rewriting your query as follows to hide CASE inside an aggregate function:
WITH CTE_Employee AS (
SELECT
ID
, SUM(Perdium) AS TotalPerdium
, SUM(CASE WHEN Location='NY' THEN Perdium ELSE 0 END) AS NYPerdium
FROM EmployeePerdium
GROUP BY ID
)
SELECT
ID
, TotalPerdium
, NYPerdium/TotalPerdium AS NYPerdiumShare
FROM CTE_Employee
You don't need a cte here. Just use the sum window function.
SELECT DISTINCT
ID,
SUM(Perdium) OVER() as TotalPerdium
SUM(CASE WHEN Location='NY' THEN 1.0*Perdium ELSE 0 END) OVER(PARTITION BY ID)
/SUM(Perdium) OVER() AS NYPerdium
FROM EmployeePerdium
I have a table that has some duplicates. I can count the distinct records to get the Total Volume. When I try to Sum when the CompTia Code is B92 and run distinct is still counts the dupes.
Here is the query:
select
a.repair_week_period,
count(distinct a.notif_id) as Total_Volume,
sum(distinct case when a.header_comptia_cd = 'B92' then 1 else 0 end) as B92_Sum
FROM artemis_biz_app.aca_service_event a
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
group by 1
order by 1
;
Is There a way to only SUM the distinct records for B92?
I also tried inner joining the table on itself by selecting the distinct notification id and joining on that notification id, but still getting wrong sum counts.
Thanks!
Your B92_Sum currently returns either NULL, 1 or 2, this is definitely no sum.
To sum distinct values you need something like
sum(distinct case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end)
If this column_to_sum is actually the notif_id you get a conditional count but not a sum.
Otherwise the distinct might remove too many vales and then you probably need a Derived Table where you remove duplicates before aggregation:
select
repair_week_period,
--no more distinct needed
count(a.notif_id) as Total_Volume,
sum(case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end) as B92_Sum
FROM
(
select repair_week_period,
notif_id
header_comptia_cd,
column_to_sum
from artemis_biz_app.aca_service_event
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
-- only onw row per notif_id
qualify row_number() over (partition by notif_id order by ???) = 1
) a
group by 1
order by 1
;
#dnoeth It seems the solution to my problem was not to SUM the data, but to count distinct it.
This is how I resolved my problem:
count(distinct case when a.header_comptia_cd = 'B92' then a.notif_id else NULL end) as B92_Sum
I have a simple sql query which return the data as
select [BusinessModel], count(*) As Total from DimHotelExpand
group by [BusinessModel]
The result comes as:
DA 53894
DL 7098
ECM 1472
Flex 14789
GDS 33487
Lead 1499050
MT 71306
Unknown 572467
I want the row with value 'Lead' to appear at the bottom of the result. How can I do this?
You can try this, if you don't know if Lead has always the biggest value:
select
[BusinessModel], count(*) As Total
from DimHotelExpand
group by
[BusinessModel]
order by
case [BusinessModel] when 'Lead' then 1 else 0 end asc
Try this one -
SELECT
d.BusinessModel
, Total = COUNT(1)
FROM dbo.DimHotelExpand d
GROUP BY d.BusinessModel
ORDER BY
CASE WHEN d.BusinessModel = 'Lead' THEN 0 ELSE 1 END
, Total
You can order it by your total column (since Lead's count is higher) like this:
SELECT [BusinessModel], count(*) As Total from DimHotelExpand
GROUP BY [BusinessModel]
ORDER BY count(*)
You can try with "union all".
select [BusinessModel], count(*) As Total from DimHotelExpand
where [BusinessModel] <> 'Lead'
group by [BusinessModel]
union all
select [BusinessModel], count(*) As Total from DimHotelExpand
where [BusinessModel] = 'Lead'
group by [BusinessModel]
A solution with "Order by", I believe don't work fine. Only work fine while "Lead" is more greater bussines model.
I think frikozoid solution is also valid.
I know this question might be repeated ... But I have query like this, I have a field "Compute_CRM_State" in my table. And that field contains data like "approved,pending,cancelled" but now i want to fetch total count of approved or pending or cancelled. I tried it with sub query. I can able to get total count of approved or pending or cancelled but.. I got same records many times.
query :
SELECT (SELECT COUNT(Compute_CRM_State) AS Expr1
FROM CRM_Doctor_Request
WHERE (CRM_State_Id = 1)) AS PENDING,
(SELECT COUNT(Compute_CRM_State) AS Expr2
FROM CRM_Doctor_Request AS CRM_Doctor_Request_3
WHERE (CRM_State_Id = 2)) AS Approved,
(SELECT COUNT(Compute_CRM_State) AS Expr3
FROM CRM_Doctor_Request AS CRM_Doctor_Request_2
WHERE (CRM_State_Id = 3)) AS CANCELLED
FROM CRM_Doctor_Request AS CRM_Doctor_Request_1
There should be display only 1 record of count.. but it is getting display the number of times that number of records in table contains.
The reason you were not getting the total count correctly and getting many records instead, is that the COUNTs are selected as a correlated subquery, so you will got the count for each record in the table.
To fix that you have to use the aggregate function in the outer query, not from the correlated subuery. And to get those total count for each status, use the CASE expression to do this like so:
SELECT
SUM(CASE WHEN CRM_State_Id = 1 THEN 1 ELSE 0 END) AS PENDING,
SUM(CASE WHEN CRM_State_Id = 2 THEN 1 ELSE 0 END) AS Approved,
SUM(CASE WHEN CRM_State_Id = 3 THEN 1 ELSE 0 END) AS CANCELLED
FROM CRM_Doctor_Request;
SQL Fiddle Demo
Or: you can use the PIVOT table operator to do the same thing:
SELECT
[1] AS PENDING,
[2] AS Approved,
[3] AS Cancelled
FROM
(
SELECT * FROM CRM_Doctor_Request
) AS t
PIVOT
(
COUNT(Compute_CRM_State)
FOR CRM_State_Id IN([1], [2], [3])
) AS p;
Like this.