How best to Count(*) with a CASE STATEMENT? - sql

The following SQL (on SQL Server) returns an error of:
Incorrect syntax near '*'
Is there something inherently wrong with using the following SELECT statement?:
SELECT
COUNT(CASE WHEN <conditions> THEN * ELSE NULL END) as conditionalcountall
FROM TABLE
I tried this variation which also failed:
SELECT
CASE WHEN <conditions> THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM TABLE

I tend to like sum()
SELECT
SUM(CASE WHEN <conditions> THEN 1 ELSE 0 END) as conditionalcountall
FROM TABLE

Try This, it is Tested
SELECT
CASE WHEN 1 = 1 THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM TABLE
1 = 1is example conditions
Demo:-
Create table #temp (id int , col1 varchar (10))
go
insert into #temp values (1 , 'aaaa')
insert into #temp values (2 , 'bbbb')
insert into #temp values (3 , 'cccc')
SELECT
CASE WHEN 1 = 1 THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM #temp
Result:
In Case Condation like that id = 1 you should select Count(*) in CASE cluse in your query
like this:
SELECT
CASE WHEN id = 1 THEN (select COUNT(*) from #temp) ELSE NULL END as conditionalcountall
FROM #temp
Result:-
Note: if You used Count(*) directly, you counted the id column, so you should use group by as next:
SELECT
CASE WHEN id = 1 THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM #temp
group by id
Result:

SELECT
CASE WHEN X THEN Y
ELSE Z
END *NEW COLUMN NAME*
, COUNT(*)
FROM
TABLE
GROUP BY
*NEW COLUMN NAME*
This should return two columns, one with the buckets/case statement and one with the count of the columns for each one of your buckets
This method was the most straightforward for myself

If you REALLY, REALLY want to use COUNT, then you can do this:
SELECT
COUNT(*)
FROM table
WHERE <conditions>

Related

How to check If table contains diferent values?

I have table:
Id Value
1 79868
2 79868
3 79868
4 97889
5 97889
Now, I want to make next select with bool variable that check if table contains difrent values at table column Value. Something like this:
select
v= (select case when exists(...)
then 1
else 0
end)
Table contais Values: 79868, 97889 so v should return 1 in other case 0.
How to write select iniside select case??
You can compare the min and max values:
select (case when (select min(value) from t) = (select max(value) from t)
then 1 else 0
end) as all_same
With an index on (value), this should be quite fast.
The above solution assumes that there are no null values or that NULL values should be ignored.
You might try this:
SELECT CASE COUNT(*)
WHEN 1 THEN 1
ELSE 0
END AS all_equal
FROM (SELECT DISTINCT Value FROM my_table);
If I get your question correct, you want to check if value column contains more than 1 distinct values. You can achieve this using,
select (case when count(value) > 1 then 1 else 0 end) as out
from (select value from table group by value) temp
May this is better:
SELECT CASE COUNT(DISTINCT value) WHEN 1 THEN 1
ELSE 0
END AS all_equal
FROM my_table;
So, you just need one case expression with two Boolean variable
declare #bit1 bit = 1, #bit0 bit = 0
select
(case when min(value) = max(value) then #bit1 else #bit0 end) as v
from table t
where value is not null
This is a the same as another answers
But is has some test data
declare #T table(pk int identity primary key, val int not null);
insert into #T (val) values (79868), (79868), (79868);
select case when count(distinct(val)) = 1 then 0 else 1 end as dd
from #t t;
select case when min(val) = max(val) then 0 else 1 end as dd
from #t t;
insert into #T (val) values (97889), (97889);
select case when count(distinct(val)) = 1 then 0 else 1 end as dd
from #t t;
select case when min(val) = max(val) then 0 else 1 end as dd
from #t t;
I like the min max answer from Gordon best

sql select statement select sum where

I have two temp tables (below), the first marks one of five conditions. The second pulls from that table and does a sum and a count based on the condition. How could I get the second table to work with this, or a similar format?
select ID
,sum_value
,condition_field
,'condition_1' = case when condition_type in (1,2) then 1 else 0 end
,'condition_2' = case when condition_type in (3,4) then 1 else 0 end
--etc...
into #temp
from my_table
select ID
,sum_value
,'1_amt' = SUM(sum_value) from #temp where condition_1 = 1
,'1_cnt' = COUNT(ID) from #temp where condition_1 = 1
,'2_amt' = SUM(sum_value) from #temp where condition_2 = 1
,'2_cnt' = COUNT(ID) form #temp where condition_2 = 2
from #temp
You want something more like this:
SUM(CASE WHEN condition_1=1 THEN sum_value ELSE 0 END) AS 1_amt

SQL Query to add result set values as column values

I want to add the below queries as the column values without creating a table.
Select 'NetworkKey' as AuthKey
Select count(NetworkSK) as Totalcount from EDW.Fact.AuthorizationRequest
Select count(*) as NUllcount from EDW.Fact.AuthorizationRequest where NetworkSK is NULL
Select count(*) as NotNullcount from EDW.Fact.AuthorizationRequest where NetworkSK is Not NULL
My result should look like this without creating a table physically...
AuthKey Totalcount Nullcount NotNullCount
NetworkKey 100 5 95
YOU WANT TO DO IT LIKE THIS BECAUSE THIS WILL WORK TO SOLVE YOUR PROBLEM.
SELECT 'NetworkKey' AS AuthKey,
COUNT(*) AS TotalCount,
SUM(CASE WHEN NetworkSK IS NULL THEN 1 ELSE 0 END) AS NUllcount,
SUM(CASE WHEN NetworkSK IS NOT NULL THEN 1 ELSE 0 END) AS NotNullcount
FROM EDW.Fact.AuthorizationRequest
Happy holidays.

Select statement to return constant when no records found in table in SQL Server 2008

I am have a table with data and now i need to return zero in select statement if there is no records in table for example. I need to use it in Stored Procedure.
-- If no records exists in below select statement
SELECT ID,Text,Date FROM tblData WHERE ID = 12
IF (##ROWCOUNT = 0)
BEGIN
SELECT -5 AS ID
END
Output:
ID Text Date
ID
-5
Expected output
ID
-5
If you want to return 1 row even when there is no match, you can use aggregation:
SELECT (CASE WHEN COUNT(*) = 0 THEN -5 ELSE MAX(ID) END) as ID
FROM tblData
WHERE ID = 12;
I always use an Exists statment.
if exists(SELECT ID FROM tblData WHERE ID = 12)
select 0 as RowsExist
else
select 1 as RowsExist
For a single scalar value you could use something like;
SELECT ISNULL((SELECT ID FROM tblData WHERE ID = 12), 0) as ID
Rhys
SELECT (CASE WHEN Ta.ID IS NULL THEN TBL.ID
ELSE Ta.ID END) AS ID,Ta.Text,Ta.Date
FROM (VALUES(-5)) AS TBL(ID)
LEFT JOIN
(
SELECT ID,Text,Date FROM tblData WHERE ID = 12
)
AS Ta ON Ta.ID = Ta.ID

Counting null and non-null values in a single query

I have a table
create table us
(
a number
);
Now I have data like:
a
1
2
3
4
null
null
null
8
9
Now I need a single query to count null and not null values in column a
This works for Oracle and SQL Server (you might be able to get it to work on another RDBMS):
select sum(case when a is null then 1 else 0 end) count_nulls
, count(a) count_not_nulls
from us;
Or:
select count(*) - count(a), count(a) from us;
If I understood correctly you want to count all NULL and all NOT NULL in a column...
If that is correct:
SELECT count(*) FROM us WHERE a IS NULL
UNION ALL
SELECT count(*) FROM us WHERE a IS NOT NULL
Edited to have the full query, after reading the comments :]
SELECT COUNT(*), 'null_tally' AS narrative
FROM us
WHERE a IS NULL
UNION
SELECT COUNT(*), 'not_null_tally' AS narrative
FROM us
WHERE a IS NOT NULL;
Here is a quick and dirty version that works on Oracle :
select sum(case a when null then 1 else 0) "Null values",
sum(case a when null then 0 else 1) "Non-null values"
from us
for non nulls
select count(a)
from us
for nulls
select count(*)
from us
minus
select count(a)
from us
Hence
SELECT COUNT(A) NOT_NULLS
FROM US
UNION
SELECT COUNT(*) - COUNT(A) NULLS
FROM US
ought to do the job
Better in that the column titles come out correct.
SELECT COUNT(A) NOT_NULL, COUNT(*) - COUNT(A) NULLS
FROM US
In some testing on my system, it costs a full table scan.
As i understood your query, You just run this script and get Total Null,Total NotNull rows,
select count(*) - count(a) as 'Null', count(a) as 'Not Null' from us;
usually i use this trick
select sum(case when a is null then 0 else 1 end) as count_notnull,
sum(case when a is null then 1 else 0 end) as count_null
from tab
group by a
Just to provide yet another alternative, Postgres 9.4+ allows applying a FILTER to aggregates:
SELECT
COUNT(*) FILTER (WHERE a IS NULL) count_nulls,
COUNT(*) FILTER (WHERE a IS NOT NULL) count_not_nulls
FROM us;
SQLFiddle: http://sqlfiddle.com/#!17/80a24/5
This is little tricky. Assume the table has just one column, then the Count(1) and Count(*) will give different values.
set nocount on
declare #table1 table (empid int)
insert #table1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(NULL),(11),(12),(NULL),(13),(14);
select * from #table1
select COUNT(1) as "COUNT(1)" from #table1
select COUNT(empid) "Count(empid)" from #table1
Query Results
As you can see in the image, The first result shows the table has 16 rows. out of which two rows are NULL. So when we use Count(*) the query engine counts the number of rows, So we got count result as 16. But in case of Count(empid) it counted the non-NULL-values in the column empid. So we got the result as 14.
so whenever we are using COUNT(Column) make sure we take care of NULL values as shown below.
select COUNT(isnull(empid,1)) from #table1
will count both NULL and Non-NULL values.
Note: Same thing applies even when the table is made up of more than one column. Count(1) will give total number of rows irrespective of NULL/Non-NULL values. Only when the column values are counted using Count(Column) we need to take care of NULL values.
I had a similar issue: to count all distinct values, counting null values as 1, too. A simple count doesn't work in this case, as it does not take null values into account.
Here's a snippet that works on SQL and does not involve selection of new values.
Basically, once performed the distinct, also return the row number in a new column (n) using the row_number() function, then perform a count on that column:
SELECT COUNT(n)
FROM (
SELECT *, row_number() OVER (ORDER BY [MyColumn] ASC) n
FROM (
SELECT DISTINCT [MyColumn]
FROM [MyTable]
) items
) distinctItems
Try this..
SELECT CASE
WHEN a IS NULL THEN 'Null'
ELSE 'Not Null'
END a,
Count(1)
FROM us
GROUP BY CASE
WHEN a IS NULL THEN 'Null'
ELSE 'Not Null'
END
Here are two solutions:
Select count(columnname) as countofNotNulls, count(isnull(columnname,1))-count(columnname) AS Countofnulls from table name
OR
Select count(columnname) as countofNotNulls, count(*)-count(columnname) AS Countofnulls from table name
Try
SELECT
SUM(ISNULL(a)) AS all_null,
SUM(!ISNULL(a)) AS all_not_null
FROM us;
Simple!
If you're using MS Sql Server...
SELECT COUNT(0) AS 'Null_ColumnA_Records',
(
SELECT COUNT(0)
FROM your_table
WHERE ColumnA IS NOT NULL
) AS 'NOT_Null_ColumnA_Records'
FROM your_table
WHERE ColumnA IS NULL;
I don't recomend you doing this... but here you have it (in the same table as result)
use ISNULL embedded function.
All the answers are either wrong or extremely out of date.
The simple and correct way of doing this query is using COUNT_IF function.
SELECT
COUNT_IF(a IS NULL) AS nulls,
COUNT_IF(a IS NOT NULL) AS not_nulls
FROM
us
SELECT SUM(NULLs) AS 'NULLS', SUM(NOTNULLs) AS 'NOTNULLs' FROM
(select count(*) AS 'NULLs', 0 as 'NOTNULLs' FROM us WHERE a is null
UNION select 0 as 'NULLs', count(*) AS 'NOTNULLs' FROM us WHERE a is not null) AS x
It's fugly, but it will return a single record with 2 cols indicating the count of nulls vs non nulls.
This works in T-SQL. If you're just counting the number of something and you want to include the nulls, use COALESCE instead of case.
IF OBJECT_ID('tempdb..#us') IS NOT NULL
DROP TABLE #us
CREATE TABLE #us
(
a INT NULL
);
INSERT INTO #us VALUES (1),(2),(3),(4),(NULL),(NULL),(NULL),(8),(9)
SELECT * FROM #us
SELECT CASE WHEN a IS NULL THEN 'NULL' ELSE 'NON-NULL' END AS 'NULL?',
COUNT(CASE WHEN a IS NULL THEN 'NULL' ELSE 'NON-NULL' END) AS 'Count'
FROM #us
GROUP BY CASE WHEN a IS NULL THEN 'NULL' ELSE 'NON-NULL' END
SELECT COALESCE(CAST(a AS NVARCHAR),'NULL') AS a,
COUNT(COALESCE(CAST(a AS NVARCHAR),'NULL')) AS 'Count'
FROM #us
GROUP BY COALESCE(CAST(a AS NVARCHAR),'NULL')
Building off of Alberto, I added the rollup.
SELECT [Narrative] = CASE
WHEN [Narrative] IS NULL THEN 'count_total' ELSE [Narrative] END
,[Count]=SUM([Count]) FROM (SELECT COUNT(*) [Count], 'count_nulls' AS [Narrative]
FROM [CrmDW].[CRM].[User]
WHERE [EmployeeID] IS NULL
UNION
SELECT COUNT(*), 'count_not_nulls ' AS narrative
FROM [CrmDW].[CRM].[User]
WHERE [EmployeeID] IS NOT NULL) S
GROUP BY [Narrative] WITH CUBE;
SELECT
ALL_VALUES
,COUNT(ALL_VALUES)
FROM(
SELECT
NVL2(A,'NOT NULL','NULL') AS ALL_VALUES
,NVL(A,0)
FROM US
)
GROUP BY ALL_VALUES
select count(isnull(NullableColumn,-1))
if its mysql, you can try something like this.
select
(select count(*) from TABLENAME WHERE a = 'null') as total_null,
(select count(*) from TABLENAME WHERE a != 'null') as total_not_null
FROM TABLENAME
Just in case you wanted it in a single record:
select
(select count(*) from tbl where colName is null) Nulls,
(select count(*) from tbl where colName is not null) NonNulls
;-)
for counting not null values
select count(*) from us where a is not null;
for counting null values
select count(*) from us where a is null;
I created the table in postgres 10 and both of the following worked:
select count(*) from us
and
select count(a is null) from us
In my case I wanted the "null distribution" amongst multiple columns:
SELECT
(CASE WHEN a IS NULL THEN 'NULL' ELSE 'NOT-NULL' END) AS a_null,
(CASE WHEN b IS NULL THEN 'NULL' ELSE 'NOT-NULL' END) AS b_null,
(CASE WHEN c IS NULL THEN 'NULL' ELSE 'NOT-NULL' END) AS c_null,
...
count(*)
FROM us
GROUP BY 1, 2, 3,...
ORDER BY 1, 2, 3,...
As per the '...' it is easily extendable to more columns, as many as needed
Number of elements where a is null:
select count(a) from us where a is null;
Number of elements where a is not null:
select count(a) from us where a is not null;