Error: Cannot perform an aggregate function SQL - sql

1.) I am getting an error for using SUM function in SQL is there a possible way to fix this, I tried searching the internet, but most of the examples are for single column.
SELECT
r.WorkOrderBatch,
wo.ProductCode,
wo.WorkOrderQty,
Convert(DATE,wo.StartDate),
wo.CurrentStatus,

replace this line:
SUM(COUNT(CASE r.IsTestPass WHEN 1 THEN NULL ELSE 1 END)) AS FailedQty
With
SUM(CASE r.IsTestPass WHEN 1 THEN 0 ELSE 1 END) AS FailedQty
rest everything looks good

Related

SQL Creating a function to get the sum based on column name

Im trying to write a simple function that will allow me to get the sum based off the value of a column.
CREATE FUNCTION [GetSumOfColumnByCase](#column varchar(50), #case int)
RETURNS INT
AS
BEGIN
declare #return int
set #return = SUM(CASE WHEN #column = #case THEN 1 ELSE 0 END)
-- Return the result of the function
return #return
END
GO
I call this function like this:
SELECT HouseDescription,
[dbo].[GetSumOfColumnByCase]([HouseTypeId], 1) AS "houseType1",
[dbo].[GetSumOfColumnByCase]([HouseTypeId], 2) AS "houseType2"
Doing things this way forces me to GROUP BY both the houseDescription and the HouseTypeId columns but i just want to GROUP BY the housedescription.
If i do things this way:
SELECT HouseDescription,
SUM(CASE WHEN HouseTypeId = 1 THEN 1 ELSE 0 END) AS "houseType1",
SUM(CASE WHEN HouseTypeId = 2 THEN 1 ELSE 0 END) AS "houseType2"
Its fine, it doesnt force me to GROUP BY HouseTypeId.
Can anyone explain why this is?
When you are using a GROUP BY clause, every column needs to either be in the GROUP BY, or it needs to be aggregated.
In your second example, you are fulfilling these requirements - by placing the SUM around the function call. In your first example, since the function call itself isn't wrapped in an aggregation (SUM, MAX, MIN, etc.), you must place it in the GROUP BY clause in order to not trigger an error.
https://msdn.microsoft.com/en-us/library/ms177673.aspx
I agree with Gordon though, you may want to rethink your strategy for this.
You cannot do what you want with a function, because SQL Server does not support dynamic SQL (readily) in functions. And to handle any column, you would need dynamic SQL.
But, you don't need that anyway. If you want the sum on each row of the original data, you want window functions:
SELECT SUM(CASE WHEN HouseTypeId = 1 THEN 1 ELSE 0 END) OVER () AS houseType1,
SUM(CASE WHEN HouseTypeId = 2 THEN 1 ELSE 0 END) OVER () AS houseType2
. . .
Aggregation is not needed for this query.

Trouble counting null and missing values (and differentiating between the two) using RODBC package

I am working to create a a matrix of missingness for a SQL database consisting of 5 tables and nearly 10 years of data. I have established ODBC connectivity and am using the RODBC package in R as my working environment. I am trying to write a function that will output a count of rows for each year for each table, a count and percent of null values (values not present) in a given year for a given table, and a count and percent of missing (questions skipped/not answered) values for a given table. I am working with the code below, trying to get it to work on one variable then turning it into a function once it works. However, when I run this code(see below), it appears to not be working, and I believe the issue lies with assigning an integer value to the character for null, NA. I am getting this message when trying to list vars in the function:
Error in as.environment(pos) : no item called "22018 245 [Microsoft][ODBC SQL Server Driver][SQL Server]Conversion failed when converting the varchar value 'NA' to data type int." on the search list.
Also, when I try to find the environment for the function, R returns NULL. I do not necessarily want to assign a new value to the already existent variable, and I new to SQL, but I am trying to do something along these lines If X = 'NA' then Y = 1 else 0. I get the following error message when I try to run the final 2 lines creating the percent vars:
Error in eval(substitute(expr), data, enclos = parent.frame()) : invalid 'envir' argument of type 'character'
Any insight?
test1 <- sqlQuery(channel, "select
[EVENT_YEAR] AS 'YEAR',
COUNT(*) AS 'TOTAL',
SUM(CASE WHEN MOTHER_EDUCATION_TRENDABLE = 'NA' THEN 1 ELSE 0 END) AS 'NULL_VAL',
SUM(CASE WHEN MOTHER_EDUCATION_TRENDABLE = -1 THEN 1 ELSE 0 END) AS 'MISS_VAL'
from [GA_CMH].[dbo].[BIRTHS]
GROUP BY [EVENT_YEAR]
ORDER BY [EVENT_YEAR]")
test1$nullpct<-with(test1, NULL_VAL/TOTAL)
test1$misspct<-with(test1, MISS_VAL/TOTAL)
I believe the data type of your column MOTHER_EDUCATION_TRENDABLE is an integer, if so, try:
select
[EVENT_YEAR] AS 'YEAR',
COUNT(*) AS 'TOTAL',
SUM(CASE WHEN MOTHER_EDUCATION_TRENDABLE IS NULL THEN 1 ELSE 0 END) AS 'NULL_VAL',
SUM(CASE WHEN MOTHER_EDUCATION_TRENDABLE = -1 THEN 1 ELSE 0 END) AS 'MISS_VAL'
from [GA_CMH].[dbo].[BIRTHS]
GROUP BY [EVENT_YEAR]
ORDER BY [EVENT_YEAR]

How do I find the percentage between two columns in postgresql?

Two parameters in my SELECT statement are:
count(product_code.code) as codes_allocated
count(case when product_code.taken='TRUE' then product_code.taken end) as codes_claimed
I would like to add one more parameter to my select statement that takes the codes_claimed and divides it by the codes_allocated to get a percentage of the codes claimed.
I've tried many things but always get the error:
ERROR: division by zero
Query failed.
My most recent attempt used the following:
(count(case when core_isvcode.reserved='TRUE' then core_isvcode.reserved end)::decimal / count(core_isvcode.code)::decimal)*100 as Percent_redeemed`
Any help and guidance is greatly appreciated!
why not include a CASE to validate count(core_isvcode.code) > 0
CASE WHEN count(core_isvcode.code) > 0 THEN
(count(case when core_isvcode.reserved='TRUE' then core_isvcode.reserved end)::decimal
/ count(core_isvcode.code)::decimal)*100
ELSE NULL
END as Percent_redeemed
I think nullif() is often the simplest method:
(count(case when core_isvcode.reserved='TRUE' then core_isvcode.reserved end)::decimal / nullif(count(core_isvcode.code)::decimal))*100 as Percent_redeemed
However, I think avg() is simpler for this calculation:
avg(case when core_isvcode.reserved = 'TRUE' then 100.0
when core_isvcode.reserved is null then NULL
else 0.0
end)

Combining CASE Statements in SQL

What I am trying to do is combine (2) CASE statements that each return a SUM and then take the SUM of those results. Here's what I have so far:
COUNT((
CASE (COUNT(table.CODE))
WHEN 0
THEN 0
ELSE SUM(
CASE table.CODE
WHEN '100'
THEN 1
ELSE 0
END)) (
CASE (COUNT(table.CODE))
WHEN 0
THEN 0
ELSE (SUM(
CASE table.CODE
WHEN '50'
THEN 1
ELSE 0
END))))
|| AS Total Code
I think I'm over-complicating this. The error I am receiving is Missing Keyword (at the beginning of the 2nd CASE statement). Any thoughts?
When you have an overload of parentheticals, you might find it helpful to go overboard with indention to spot problems:
COUNT
(
(
CASE (COUNT(table.CODE))
WHEN 0
THEN 0
ELSE SUM
(
CASE table.CODE
WHEN '100'
THEN 1
ELSE 0
END
)
<--Should be an END here?-->
) <--What is happening here-->
(
CASE (COUNT(table.CODE))
WHEN 0
THEN 0
ELSE
(
SUM
(
CASE table.CODE
WHEN '50'
THEN 1
ELSE 0
END
)
)
<--Should be an END here?-->
)
)
|| AS Total Code
You can see that there are two CASE statements butted up against each other with no operator to make any sense of it.
You might also spot that your first and third CASE are not closed with an END, which is what MySQL is balking about.
Lastly, that double-bar in MySQL is an "OR" operator. But you are not OR'ing anything... Not sure what the plan was here.
Ultimately, though, I think you are going to run into problems Counting a Sum in the same query. You may have to move those SUM(CASE...END) bits into a subquery and then doing the COUNT outside of that.
After looking over the answers to my questions, this is what I came up with:
CASE (COUNT(table.CODE))
WHEN 0
THEN 0
ELSE ((SUM(
CASE table.CODE
WHEN '100'
THEN 1
WHEN '50'
THEN 1
ELSE 0
END))
END) AS Value5
I'm cleaning up old code so I didn't completely understand what I was looking at because its all over the place. This is a lot cleaner and I'm positive that I am getting desired response now.

Multiple columns within a single CASE statement

I'm sure this has be covered many times so please pardon my repeat. I have a query that works but currently has 6 CASE statements within one select. Someone mentioned that it would be best optimized by putting all my WHEN conditions within a single CASE. However, I'm unable to achieve this
select right(RTRIM(region),5) as cell_id,
sum(CASE WHEN LEFT(cparty,3) in ('999','998','997') THEN chargeduration/60 else 0 END) AS OnNet_Minutes,
sum(CASE WHEN LEFT(cparty,3) in ('996','995') THEN chargeduration/60 else 0 END) AS OffNet_C_Minutes,
sum(CASE WHEN LEFT(cparty,3) in ('994','993','992') THEN chargeduration/60 else 0 END) AS OffNet_A_Minutes,
sum(CASE WHEN LEFT(cparty,3) in ('991','990') THEN chargeduration/60 else 0 END) AS OffNet_S_Minutes,
sum(CASE WHEN LEFT(cparty,2) = '00' THEN chargeduration/60 else 0 END) AS OffNet_T_Minutes,
sum(CASE WHEN len(cparty) < 6 and LEFT(cparty,1) <> 0 THEN chargeduration/60 else 0 END) AS SC_Minutes
from August.dbo.cdr20130818
where CHARGEDURATION > 0 and ISNULL(region,'''')<>'''' and LEN(region) > 5
group by right(RTRIM(region),5)
order by right(RTRIM(region),5) asc
In your case, you can't put them all into one CASE, since the results all go into different columns of the select.
BTW, you should remove your ISNULL(region, '''') <> '''' condition, as it's redundant when paired with the LEN(region) > 5 condition. (When region is null, then LEN(region) is also null, and NULL > 5 is false.)
I think you have it right, six different SUM()'s that each have meaning on their own.
If all of your criteria were in the same CASE statement you'd lose detail, you'd be returning the SUM() of your currently separate statements combined into one.
Combining redundant criteria in the WHERE clause can clean up a CASE statement, but you don't have anything completely redundant here.