SQL How to count one column when another column is distinct - sql

I have a table that looks something like this:
fin_aid_status | student_number
---------------|---------------
YES | 111222
YES | 111222
| 111333
YES | 111444
I want to count the number of fin_aid_status but not double count rows where student_number is duplicated. So the result I would like from this table would be 2. Not 3 because 111222 is in the table twice. There are many other columns in the table as well though so just looking for unique values in the table will not work.
EDIT: This is Oracle.
For example I am using code like this already:
select count(*), count(distinct student_number) from table
So for third column I would want to count the number on financial aid with unique student numbers.
So my expected output would be:
count(*) | count(distinct student_number) | count_fin_aid
4 | 3 | 2

Use a case statement to evaluate the student_number when the fin_aid_status is not null; then count the distinct values.
SELECT count(Distinct case when fin_aid_status is not null
then student_number end) as Distinct_Student
FROM tbl;
Result using sample data: 2
Given Oracle:
With cte (fin_aid_status, student_number) as (
SELECT 'YES' , 111222 from dual union all
SELECT 'YES' , 111222 from dual union all
SELECT '' , 111333 from dual union all
SELECT 'YES' , 111444 from dual )
SELECT count(Distinct case when fin_aid_status is not null
then student_number end) as DistinctStudentCnt
FROM cte;

If you are using MySQL you can write something as follows, if all you want is count
SELECT count(DISTINCT student_number) FROM your_table WHERE fin_aid_status = 'YES';

I'm assuming here, add some expected results but:
SELECT fin_aid_status,
COUNT(DISTINCT student_number)
FROM tablename
GROUP BY fin_aid_status;
Will give you count of distinct values in the student_number column for each value in the fin_aid_status column

Related

One query that matches values with only one condition out of two, one query that matches values with both conditions

I'm having some sort of a blank about how to do this in SQL.
Consider this reprex in R
set.seed(123)
data.frame(ID = (sample(c(1:5), 10, replace = T)),
status = (sample(c("yes", "no"), 10, replace = T)),
amount = (sample(seq(1,50,0.01),10)))
which gives out this table
ID status amount
1 3 no 29.87
2 3 yes 26.66
3 2 yes 15.49
4 2 yes 18.89
5 3 yes 44.06
6 5 no 30.79
7 4 yes 17.13
8 1 yes 6.54
9 2 yes 45.68
10 3 yes 12.66
I need to find two SQL queries.
One where I select the ID's that only have status of 'NO'
meaning ID 5.
and
One where I select the ID's that match both conditions, meaning ID 3
I have a query for both but I'm almost sure it's not correct so any lead is more than welcome.
Thanks
One where I select the ID's that only have status of 'NO' meaning ID 5.
select id from your_table where status='no' and id not in (select id from
your_table where status='yes')
One where I select the ID's that match both conditions, meaning ID 3
select id from your_table where status='no' and id in (select id from
your_table where status='yes')
At last I think you are expecting ids which do not match these conditions. so UNION both queries and get ids of your table which not exists after UNION
select id from your_table where id not in (
select id from your_table where status='no' and id not in
(select id from your_table where status='yes')
union all
select id from your_table where status='no' and id in
(select id from your_table where status='yes')
)

Count with different group by used in a select statement

I have a query as shown below
select sum(amount)/count(id) from tabel1 where name ='sam';
I have a table like this
name id transaction_type_id transaction_type
sam 1 23 direct
sam 1 56 direct
sam 1 21 indirect
sam 1 34 indirect
when I do count(id) am getting answer as '4' but i want it to be '2' because it have 2 transaction_type as 'direct and indirect'.please help me .
Thanks
Try this:
select sum(amount)/count(distinct transaction_type)
from tabel1
where name ='sam'
This will return a count of 2, since there are only 2 distinct transaction_type values.
Try to use:
select sum(amount)/count(distinct transaction_type) from tabel1 where name ='sam';
Try this:
SELECT
SUM(amount) / COUNT(id)
FROM tabel1
WHERE
name = 'sam'
GROUP BY
transaction_type;

SQL distinct ID and everything else

Suppose I have a table that contains the following:
CUS_ID A B
1 1 0
2 2 0
3 3 1
3 1 3
4 2 0
Is there a way to write a select statement and grab all the distinct cus_id? So basically it would only bring back one record for cus_id 3.
SELECT DISTINCT CUS_ID FROM table_name;
Or:
select
CUS_ID
-- columns below are optional and exist just to
-- help you understand for what reason 'group by' is needed
-- , count(A) cntA
-- , sum(B) sumB
from YourTable
group by
CUS_ID
order by
CUS_ID
UPD. I meant to comment whole lines :)

To find total number of rows

I have a table like this
Table1
=======
A B
8 5
2 9
null 4
2 5
How to find total number of rows from table1,note if any column value is null in a row then that row should be considered as 2 rows?
I have tried with count(*)*2 and nvl function it doesn't work
Try this
SELECT SUM(CASE WHEN A IS NULL OR B IS NULL THEN 2 ELSE 1 END) AS CountVal
FROM TABLE1
Fiddle Demo
O/P:
COUNTVAL
--------
5
COUNT() is rowbased.. you can tweak it using SUM() instead..
select sum(NVL2(a,NVL2(b,1,2),2)) FROM TABLE1
CASE as suggested by #Vignesh is the simplest and more readable !!
COUNT() can also done like this.. But NOT a optimal solution at all!
SELECT COUNT(1) FROM
(
SELECT NVL(a,NVL(b,1)) FROM TABLEA
UNION ALL
SELECT NVL(a,NVL(b,1)) FROM TABLEA
WHERE A OR B iS NULL
)

SQL: Compare rows in a same table

I'm trying to compare rows in a single table
and figure out if "addr" and "zip" under the same id are same or different.
id | addr | zip
------+----------+----------
1 | 123 | 0000
1 | 123 | 0000
1 | 123 | 0001
2 | 222 | 1000
2 | 221 | 1000
So the result should say id 1 has valid addr and invalid zip
id 2 has invalid addr and valid zip.
Any hint will be appreciated! Thank you!!
The query...
SELECT id, COUNT(DISTINCT addr), COUNT(DISTINCT zip)
FROM YOUR_TABLE
GROUP BY id
...should give the following result on your example data...
1, 1, 2
2, 2, 1
The numbers in bold greater than 1 indicate "invalid" items.
If you want to actually filter on this, you can use HAVING clause, for example:
SELECT id, COUNT(DISTINCT addr) ADDR_COUNT, COUNT(DISTINCT zip) ZIP_COUNT
FROM YOUR_TABLE
GROUP BY id
HAVING ADDR_COUNT > 1 OR ZIP_COUNT > 1
May I suggest that if you don't actually want this kind of "mismatched" data in your database, redesign your data model so duplicates cannot happen in the first place. No duplicates, no mismatches!
Group by id. Select id, COUNT(DISTINCT addr) and COUNT(DISTINCT zip) columns.
Filter the rows where the number of distinct address or zips > 1.
This will give you the ids with inconsistent duplicate data.
Example:
SELECT id, COUNT(DISTINCT addr) nAddr, COUNT(DISTINCT zip) nZip
FROM [mytable]
GROUP BY id
HAVING nAddr > 1 OR nZip > 1
Cheers,
SELECT id
, CASE s.addrcount
WHEN 1 THEN 'valid'
ELSE 'invalid' END as addrok
, CASE s.zipcount
WHEN 1 THEN 'valid'
ELSE 'invalid' END as zipok
FROM
(
SELECT id
, count(distinct addr) as addrcount
, count(distinct zip) as zipcount
FROM table1
GROUP BY id
) as s