Dividing two counts Oracle SQL - sql

I am trying to write what I thought would be a fairly simple query but is proving to be harder than I thought. I want to divide the results of two select statements:
Select count (*) from tableA where columnA = 'A'
/
Select count (*) from tableA where columnA in ('1','2')
I am using Oracle SQL Developer
Thanks for any guidance

I would recommend conditional aggregation . . . but with sum() not count():
Select (sum(case when columnA = 'A' then 1 else 0 end) /
sum(case when columnA in ('1', '2') then 1 end)
)
from tableA;
Note the lack of else in the denominator. This handles the divide-by-zero case.

You could treat the, both as subqueries within a single main query:
select
(select count (*) from tableA where columnA = 'A')
/
(select count (*) from tableA where columnA in ('1', '2'))
from dual
or if the table and column names are actually the same you could do a single query with conditional counts, something like:
select count (case when columnA = 'A' then columnA end)
/
count (case when columnA in ('1', '2') then columnA end)
from tableA
where columnA in ('A', '1', '2')
I've fixed the single quotes in both, not sure if those were just an issue with posting your question.
You may also need to add logic to handle the second count being zero, if that could happen - as that would cause a runtime error.

Related

Subtraction of two SELECT statements in SQL (redshift)

Can someone explain why the below doesn't work?
((SELECT COUNT(*) FROM Table1) - (SELECT Count(Metric) FROM Table1)) as X
Count(*) will give me all the rows in the table and Count(Metric) will give me the non-null values in the Metric column. So the difference between these will give me the number of null values in the Metric column and I have labelled this column X. I just want the difference between the two in Column X but not sure why it isn't working.
By the way, I know I can get it to work via the below:
SELECT COUNT(*) as a, count(metric) as b, COUNT(*)-COUNT(metric) as c
You would need to select the result:
SELECT ((SELECT COUNT(*) FROM Table1) - (SELECT Count(Metric) FROM Table1)) as X
But it is simpler to use conditional aggregation:
SELECT SUM(CASE WHEN Metrics IS NULL THEN 1 ELSE 0 END) X FROM table1
A SELECT query needs to start with SELECT (or WITH or a parenthesis if the query is a compound query with a set operator such as UNION ALL).
One method is:
SELECT ((SELECT COUNT(*) FROM Table1) - (SELECT Count(Metric) FROM Table1)) as X
A better method is:
SELECT COUNT(*) - Count(Metric) as X
FROM Table1
Not sure about amazon-redshift, but in standard SQL I would just count the records where the field is null instead of counting all minus where they are not null.
SELECT COUNT(*) FROM Table1 WHERE Metric IS NULL;

SQL Function for Counting Multiple Variables as "Both"

In this scenario there are two columns.
Column A = Case ID ( a unique ID for the record)
Column B = Gender possible values are Male, Female
Caveat
If a Case ID is associated with multiple genders it can have multiple records.
Example Data Set:
ColumnA ColumnB
Case001 Male
Case001 Female
Case002 Male
Case003 Female
data set continues...
Question: I would like to categorize results as in Case001 where there are two results as "Both". What would be the best way to apporach this solution? Is there a formula or standard way to accomplish this?
Sample Desired Data Set:
ColumnA ColumnB
Case001 Both
Case002 Male
Case003 Female
data set continues...
Thank you!
I can accomplish with case statement and sub queries. However, I expect there to be a better solution.
You can use EXISTS in a CASE statement:
select distinct
t.ColumnA,
case
when exists (
select 1 from tablename
where ColumnA = t.ColumnA and ColumnB <> t.ColumnB
) then 'Both'
else t.ColumnB
end
from tablename t
Use aggregation and a case expression:
select col1,
(case when min(gender) = max(gender) then min(gender)
else 'both'
end) as gender
from cases c
group by col1;
group by with having clauses combined by union all as below might be a good alternative :
with t( ColumnA, ColumnB ) as
(
select 'Case001', 'Male' union all
select 'Case001', 'Female' union all
select 'Case002', 'Male' union all
select 'Case003', 'Female'
)
select ColumnA, 'Both' ColumnB from t group by ColumnA having count(distinct ColumnB) = 2
union all
select ColumnA, max(ColumnB) from t group by ColumnA having count(distinct ColumnB) = 1;
ColumnA ColumnB
------- -------
Case001 Both
Case002 Male
Case003 Female
Since, there are only two possible cases for genders as having one of them or both of them
Demo

(Oracle) SQL: Column must contain a list of values

I'm trying to figure out an efficient (Oracle) SQL statement that verifies whether a column contains a specific list of values at least once.
One option would be to filter for that list, output all distinct values and then count them. So, something like this:
SELECT count(*)
FROM (
SELECT DISTINCT columnname
FROM table
WHERE columnname in ('a', 'b', 'c')
)
;
(And then check whether count(*) returns the number 3)
The problem with this is that the DISTINCT statement looks at the whole table, which is very bad performance-wise. All three values of my list could be at the very beginning, so i don't need to look at the millions of other rows. I only want to know that the column contains 'a', 'b' and 'c'.
Does anyone has an idea to solve this efficiently?
Thanks in advance!
It might be more efficient to look for each value individually:
select (case when exists (select 1 from t where col = 'a') and
exists (select 1 from t where col = 'b') and
exists (select 1 from t where col = 'c')
then 1 else 0
end) as has_all_three_flag
from dual;
This will be better particularly with an index on t(col).
If you wish to get rid of distinct, then try the below, Group by has better performance than distinct, See here.
SELECT count(*)
FROM (
SELECT columnname
FROM table
WHERE columnname in ('a', 'b', 'c')
GROUP BY columnname
)
;
Or you can avoid the usage of subquery by
SELECT count(DISTINCT columnname)
FROM table
WHERE columnname in ('a', 'b', 'c');

Why does count( distinct ) with NULL columns return 0 in Hive SQL?

I have struggled with an issue in Hive SQL and just found out what the issue was:
select distinct 'A', NULL;
returns 'A', NULL
select count(distinct 'A', NULL);
returns 0
select count(distinct 'A', coalesce(NULL,''));
returns 1.
I was using the select line inside of a larger query and filtered on the result (=1). With the outcome being 0, I lost a lot of rows.
How come that a row with NULL column does not contribute to the result of a count(distinct) query?
It's the interface of count in hive:
count(*) counts all rows
count(col1) counts all rows where col1 is not null
count(distinct col1,col2...) counts all distinct rows where the specified columns are not null
As a solution to your specific problem, you can try to have a nested query with the logic and use count(*) in the outer query:
select count(*) from (select distinct 'A', NULL) a;
returns 1

sql query where null results get placed first

select *
from tableA
order by cast(columnA as int), column B.
This is my current query script. There is a scenario where there column A is null. And result rows where column A is null are pushed to the end.
Is there a way such that if columnA is null, put the rows before other rows where columnA is not null?
thanks.
Something along these lines should work if your dbms supports standard SQL.
select (case when columnA is null then 0 else 1 end) as sort_order, *
from tableA
order by sort_order, columnA, columnB;
Try like below... it will help you....
SELECT * FROM tableA ORDER BY (CASE WHEN columnA IS NULL THEN 1 ELSE 0 END) DESC,
CAST(columnA as int), column B
It display the NULL results before NOT NULL Results
I case of Oracle you can use order by columnA NULLS FIRST, columnB