How to have condition inside count SQL? - sql

I already tried this code:
SELECT Count(Gender) As MaleCount, Count(Gender) As FemaleCount
FROM [Session4].[dbo].[Survey]
Where Gender = 'M' or Gender = 'F'
I can't get the accurate data when counting with two different conditions in one query.
Pictures below:
This is the result.
This is the original data
SELECT TOP (1000) [Departure]
,[Arrival]
,[Age]
,[Gender]
,[CabinType]
,[Q1]
,[Q2]
,[Q3]
,[Q4]
FROM [Session4].[DBO].[Survey]

count explain :
COUNT(*) counts all rows
COUNT(column) counts non-null value
COUNT(distinct column) counts distinct non-null value
COUNT(1) is the same as COUNT(*)
Use case/when + sum :
SELECT
sum(case when Gender = 'M' then 1 else 0 end ) As MaleCount,
sum(case when Gender = 'F' then 1 else 0 end ) As FemaleCount
FROM [Session4].[dbo].[Survey]
will produce somethings like this :
MaleCount | FemaleCount
1000 | 1255
Another way is using simple goup by
SELECT
Gender,
Count(*)
FROM [Session4].[dbo].[Survey]
GROUP BY
Gender
will produce :
Gender | Count
M | 1000
F | 1255

Try this out:
SELECT sum(case when Gender = 'M' then 1 else 0 end) As MaleCount,
sum(case when Gender = 'F' then 1 else 0 end) As FemaleCount
FROM [Session4].[dbo].[Survey]
Let me know in case of any doubts.

Related

SQL query to get count of distinct values of columns in a same table

I have table with columns like Gender, Status.
The table value is something like this
ID
Gender
Status
1
Male
A01
2
Male
3
Female
A02
4
Female
5
Unknown
6
Male
7
Female
8
Unknown
I want to display
Gender
Status
Count
Male
A01
1
Female
A02
1
Unknown
0
I tried
SELECT
t3.Gender, t3.Status, COUNT(*) AS count
FROM
(SELECT DISTINCT
t1.Gender, t1.Status
FROM
Consumer AS t1
CROSS JOIN
Consumer AS t2
WHERE
t1.Status <> t2.Status
OR t1.Status <> t2.Status) AS t3
GROUP BY
t3.Gender, t3.Status
The final output something I want to display is
Please help on this. Thanks
Since the desired results have now been updated, the solution is now much different.
Try:
SELECT
CASE WHEN GROUPING(Status) = 1 THEN 'Total' ELSE Status END AS Status,
--ISNULL(Status, 'Total') AS Status, -- This would not work is actual Status might be null
COUNT(CASE WHEN Gender = 'Female' THEN 1 END) AS Female,
COUNT(CASE WHEN Gender = 'Male' THEN 1 END) AS Male,
COUNT(CASE WHEN Gender = 'Unknown' THEN 1 END) AS Unknown,
COUNT(*) AS Count
FROM #Consumer
WHERE Status > ''
GROUP BY Status WITH Rollup
ORDER BY GROUPING(Status), Status
The above uses conditional aggregation to get the partial counts. WITH ROLLUP automatically creates a totals row. The ISNULL() sets a status label for that row (which would otherwise display as null). lastly, the GROUPING() in the ORDER BY places the rollup/total after the detail rows.
See this db<>fiddle or this one with expanded test data.
There are also ways to do this using a pivot table, but the above may be sufficient for your current needs.
select *
,Male + Female + Unknown as count
from t
pivot(count(id) for gender in(Male, Female, Unknown))p
where status is not null
union all
select 'Total'
,count(case when gender = 'Male' then status end) as Male
,count(case when gender = 'Female' then status end) as Female
,count(case when gender = 'Unknown' then status end) as Unknown
,count(status) as Total
from t
Status
Male
Female
Unknown
count
A01
1
0
0
1
A02
0
1
0
1
Total
1
1
0
2
Fiddle
You might be overthinking your requirements. Perhaps the following will work:
SELECT Gender, Status, COUNT(*) AS count
FROM Consumer
GROUP BY Gender, Status
ORDER BY Gender, Status
It was not clear what you were expecting in your results for unknown gender. If you need special handling for unknown gender and/or blank status, you can add a WHERE condition to the above for the normal cases and the UNION ALL the results with a second query to handle the special cases.
SELECT Gender, Status, COUNT(*) AS count
FROM Consumer
WHERE Gender <> 'Unknown' AND Status > ''
GROUP BY Gender, Status
UNION ALL
SELECT 'Unknown' AS Gender, '' AS Status, COUNT(*) AS count
FROM Consumer
WHERE NOT (Gender <> 'Unknown' AND Status > '')

How to find number of nulls in a table SQL

Let's say that I have an employee table. And it has columns like name, salary, and age. If I want to check if there any nulls in the name. I gotta write
SELECT name FROM EMPLOYEE
WHERE name IS NULL;
But what should I do to see the number of nulls each column has?
Probably the simplest method is:
select count(*) - count(name) as num_name_nulls,
count(*) - count(col1) as num_col1_nulls,
. . .
from employee;
However, what I do in this situation is just select the counts:
select count(*), count(name), count(col1), . . .
from employee;
Then I eyeball the result to see if the counts are not equal.
I assume you want to see nulls for a column, you can apply conditional aggregation.
SELECT COUNT(CASE WHEN name is null then 1 end) AS Name_NullCount,
COUNT(CASE WHEN salary is null then 1 end) as salary_nullCount,
COUNT(CASE WHEN age is null then 1 end) as age_nullcount
FROM EMPLOYEE;
You can use below query but it depends on number of columns. It will give number of nulls each row has.
select
((case when column1 is null then 1 else 0 end)
+ (case when column2 is null then 1 else 0 end)
----------------------------------------
----------------------------------------
+(case when columnN is null then 1 else 0 end))
from TableName
For your case
select
((case when name is null then 1 else 0 end)
+(case when salary is null then 1 else 0 end)
+(case when age is null then 1 else 0 end))
from employee
you can find Null values per row from following query
SELECT
(
(CASE WHEN name IS NULL THEN 1 ELSE 0 END)+
...
...
+(CASE WHEN colName IS NULL THEN 1 ELSE 0 END)
) AS sum_of_nulls
FROM EMPLOYEE
WHERE EmpId = 49
where colName is your Db Column Name
select
sum(case
when name is null then 1
when name is not null tehn 0
end) cname,
sum(case
when salary is null then 1
when salary is not null then 0
end) csalary,
...
from employee
limit 1;

Result set should be in single row - SQL

Table Name: Employee
Columns: EmpID, EmpName, Gender
Total count of records present in the employee table is 10
in that 6 records having gender as male and 4 records are having gender as female
i want output like below in single line
Result - > 10,6,4
Please help on the query part
Just use conditional aggregation:
select count(*), sum(case when gender = 'male' then 1 else 0 end),
sum(case when gender = 'female' then 1 else 0 end)
from t;

count(*) based on the gender condition

I have the following table in oracle10g.
state gender avg_sal status
NC M 5200 Single
OH F 3800 Married
AR M 8800 Married
AR F 6200 Single
TN M 4200 Single
NC F 4500 Single
I am trying to form the following report based on some condition. The report should look like the one below. I tried the below query but count(*) is not working as expected
state gender no.of males no.of females avg_sal_men avg_sal_women
NC M 10 0 5200 0
OH F 0 5 0 3800
AR M 16 0 8800 0
AR F 0 12 0 6200
TN M 22 0 4200 0
NC F 0 8 0 4500
I tried the following query but I am not able to count based onthe no.of males and no.of females..
select State, "NO_OF MALES", "$AVG_sal", "NO_OF_FEMALES", "$AVG_SAL_FEMALE"
from(
select State,
to_char(SUM((CASE WHEN gender = 'M' THEN average_price ELSE 0 END)),'$999,999,999') as "$Avg_sal_men,
to_char(SUM((CASE WHEN gender = 'F' THEN average_price ELSE 0 END)), '$999,999,999') as "$Avg_sal_women,
(select count (*) from table where gender='M')"NO_OF MALES",
(select count (*) from table where gender='F')"NO_OF_FEMALES"
from table group by State order by state);
You can use case as an expression (which you already know...). And the subquery is unnecessary.
select State
, sum(case gender when 'M' then 1 else 0 end) as "no.of males"
, sum(case gender when 'F' then 1 else 0 end) as "no.of females"
, to_char(
SUM(
(
CASE
WHEN gender = 'M' THEN average_price
ELSE 0
END
)
)
, '$999,999,999'
) as "Avg_sal_men",
to_char(SUM((CASE WHEN gender = 'F' THEN average_price ELSE 0 END))
,'$999,999,999'
) as "Avg_sal_women"
from table
group by State;
You are Conting by this sub-query select count (*) from table where gender='M' which always count the total number of male in your whole table....and you are doing same for counting female...
So you Can Try like this...
select State, "NO_OF MALES", "$AVG_sal", "NO_OF_FEMALES", "$AVG_SAL_FEMALE"
from(
select State,
to_char(SUM((CASE WHEN gender = 'M' THEN average_price ELSE 0 END)),'$999,999,999') as "$Avg_sal_men",
to_char(SUM((CASE WHEN gender = 'F' THEN average_price ELSE 0 END)), '$999,999,999') as "$Avg_sal_women,
Sum(Case when gender='M' then 1 else 0 end) "NO_OF MALES",
Sum(Case when gender='F' then 1 else 0 end) "NO_OF_FEMALES"
from table group by State order by state);
Try the following.
select state
,sum(case when gender = 'M' then 1 else 0 end) as nof_males
,sum(case when gender = 'F' then 1 else 0 end) as nof_females
,avg(case when gender = 'M' then average_price end) as avg_sal_male
,avg(case when gender = 'F' then average_price end) as avg_sal_female
from table
group
by state;
..add formatting as required.

SQL query to transform combination of values into a column

I have a table like this:
user_id, gender, sent
1 M 100
1 F 120
2 M 20
2 F 30
I want a table like this from the above:
user_id, male_sent, female_sent, total_sent
1 100 120 220
2 20 30 50
I lack the (Postgres) SQL foo to figure this one out.
You can use an aggregate function with a CASE expression to get the result:
select user_id,
sum(case when gender = 'M' then sent else 0 end) male_sent,
sum(case when gender = 'F' then sent else 0 end) female_sent,
sum(sent) total_sent
from yourtable
group by user_id
See SQL Fiddle with Demo
What database are you using?
If you are using SQL Server, you could do something like this:
SELECT user_id,sum(case when gender = 'M' then sent else 0 end) as male_sent,
sum(case when gender = 'F' then sent else 0 end) as female_sent,
sum(sent) as total_sent
FROM your_table_name
GROUP BY user_id