SQL statement - use avg and count together but in different conditions - sql

Assume we have the table as follows,
id Col-1 Col-2
A 1 some text
B 0 some other text
C 3
...
Take the table above as example, I want to build one SQL statement which would output the result: 2, 2.
The first value is the avg of all col-1 values except for 0, that is (1+3)/2 = 2. (If 0 is counted, then the result would be (1+0+3)/3 = 1, which is not what I want.)
The second value is the total number of all col-2 that is not empty. So the value is 2.
P.S, I know how to create them separately. What I prefer is to create only 1 statement to get both results.

For the first you can use NULLIF as null values are ignored in aggregations such as AVG.
For the second I assume you want to only count values not NULL or empty string.
SELECT AVG(NULLIF(Col1, 0)),
COUNT(CASE WHEN Col2 <> '' THEN 1 END)
FROM T

You want conditional aggregation:
select avg(case when col1 <> 0 then col1 end) as avg_not_zero,
count(col2) as num_not_empty
from table t;
As a note: 0 does not mean that the value is empty. Often NULL is used for this purpose in SQL, although strictly speaking, NULL means an unknown value.
Note: If "empty" could mean the empty string instead of NULL:
select avg(case when col1 <> 0 then col1 end) as avg_not_zero,
count(nullif(col2, '')) as num_not_empty
from table t;

Related

SQL: How to get max over column but exclude certain values?

I have a numeric column and all I want is the maximum value in that column that does NOT exceed a certain number. I am doing this along with a group by statement, using the MAX function.
So basically if for each group, the column is 1, 2, 3, 4, 5, and I want the maximum that does not exceed 4, then in this case, the maximum for this group would be 4.
However, if the column equals 5, 6, 7, 8, then since all values exceed 4, I … actually don't care, this won't end up being displayed, so just return anything.
How do I do this? Using SQL/Oracle.
You can use conditional aggregation as follows:
Select case when count(case when col > 4 then 1 end) = count(*)
then max(col)
else max(case when col <= 4 then col end)
end as res_
From your_table t
select max(case when col>4 then 0 else col end) from table1
If that is all that the query needs to do, it is best to filter the rows with col > 4 before aggregation, in a where clause. This will reduce the amount of work done by the aggregation itself, which is the most expensive operation in the whole query.
As a side effect, "groups" where all values in the column are > 4 will not be included at all in the output. For some reporting tasks this would be a problem, but you said in your case you wouldn't show anything in the output for those groups anyway.
So, you could do something like this:
select agg_col1, agg_col2, ..., max(col) as max_col_up_to_4
from your_table
WHERE col <= 4 -- DO THE FILTERING HERE!
group by agg_col1, agg_col2, ...
;
(Here agg_col1, agg_col2, ... are, obviously, the columns by which you group for your aggregation.)

Create a Query to check if any Column in a table is Null

I have zero experience with SQL but am trying to learn how to validate tables. I am trying to see within a table if any of the columns are null.
Currently I have been going with a script that is just counting the number of nulls. I am doing this for each column. Is there a better script that I can use to check all the columns in a table?
select count(id) from schema.table where id is not null
If there are 100 records I would expect all columns to come back with 100 but if one column is null it will show a 0.
You can count each column in a single query by using sum and case:
select
sum(case when Column1 is null then 1 else 0 end) Column1NullCount
, sum(case when Column2 is null then 1 else 0 end) Column2NullCount
-- ...
, sum(case when ColumnN is null then 1 else 0 end) ColumnNNullCount
from MyScheme.MyTable

Count different values of 0 from a MySQL query

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

GROUP BY with COUNT condition

I have a result set such as:
Code No
1 *
1 -
1 4
1
1
Now i basically want a query that has 2 columns, a count for the total amount and a count for those that dont have numbers.
Code No_Number Total
1 4 5
Im assuming this needs a group by and a count but how can i do the 2 different counts in a query like this?
This is what i had so far, but i am a bit stuck with the rest of it
SELECT CODE,NO
Sum(Case when No IN ('*', '-', '') then 1 else 0 end) as Count
I think you basically just need GROUP BY:
SELECT CODE,
SUM(Case when No IN ('*', '-', '') then 1 else 0 end) as Count,
COUNT(*) as total
FROM t
GROUP BY CODE;
Well, this took a moment :-), however here it is...I have used a CASE statement to create and populate the No_Number column; the database gives the row in the original table a value of 1 if the original table value is a number or gives it a NULL and discards it from the COUNT if not. Then when it makes the count it is only recognising values which were originally numbers and ignoring everything else..
If the result set is in a table or temp table:
SELECT Code,
COUNT(CASE WHEN [No] NOT LIKE '[0-9]' THEN 1 ELSE NULL END) AS No_Number,
COUNT(Code) AS Total
FROM <tablename>
GROUP BY Code
If the result set is the product of a previous query you can use a CTE (Common Table Expression) to arrive at the required result or you could include parts of this code in the earlier query.

How to get count values for multiple values in one column

My data is like this
Name Values
A Val1
A Val1
A Val2
A Val2
A Val2
B Val1
B Val2
I want to ouput my data is this way
Name Val1Count Val2Count
A 2 3
B 1 1
I can get the Name and count(*) for Val1 with this query.
select [Name],count(*) FROM [table1]
where [values]='Val1'
group by [Name]
But I am not sure how to get the count(*) for val2 in the same row.
I tried doing this, but looks like this is not supported
select [name],#val1count= (above query for val1), #val2count = (above query for val2)
Please help. Thanks for looking.
This is called pivoting. Some databases provide a PIVOT function. However, you can also do this manually.
SELECT [Name],
SUM ( CASE WHEN [Values]='VAL1' THEN 1 ELSE 0 END ) AS Val1Count,
SUM ( CASE WHEN [Values]='VAL2' THEN 1 ELSE 0 END ) AS Val2Count
FROM [table1]
GROUP BY [Name]
Explanation:
The CASE WHEN ... END gives each row a "boolean" value for whether or not the row matches your condition.
The SUM ( ... ) counts the number of rows which returned "true" (or 1).
The GROUP BY [Name] consolidates the rows down to one row per distinct name.
If you add conditions to a WHERE clause, the CASE WHEN will only see the rows matching your WHERE conditions.