how to count two different values from same column in oracle - sql

I have a table connection_master in that table column name status_conn have 1 value for ON conn. and 2 for OFF conn. now I want to get only counts of ON and OFF connections in one query
I want output like this
on_counts off_counts
110 55

Use conditional aggregation:
SELECT
COUNT(CASE WHEN status_conn = 1 THEN 1 END) AS on_counts,
COUNT(CASE WHEN status_conn = 2 THEN 1 END) AS off_counts
FROM connection_master;

SELECT COUNT(status_conn) AS CONN_ON,COUNT(status_conn) AS CONN_OFF
FROM connection_master where substr(status_conn,1,1) IN (1,2)

You can use a PIVOT:
SELECT *
FROM connection_master
PIVOT (COUNT(*) FOR status_conn IN (1 AS on_count, 2 AS off_count));
Which, for the sample data:
CREATE TABLE connection_master (status_conn) AS
SELECT 1 FROM DUAL CONNECT BY LEVEL <= 110 UNION ALL
SELECT 2 FROM DUAL CONNECT BY LEVEL <= 55;
Outputs:
ON_COUNT
OFF_COUNT
110
55
fiddle

Related

Oracle SQL grouping elements

I know this question is kind of trivial but I have difficulties writing the SQL for the example shown below.
As shown in the first table, is the result that i generated and they are ok for analytics,
REGION SUBREGION SUM
------ --------- ------
CORP CORP1 5
CORP CORP2 10
CORP CORP3 5
SB SB1 10
SB SB2 10
MID null 10
LARGE null 20
but for summary report i need to display result as shown in the second table. Any clues?
REGION SUM
------ ----
CORP 20
CORP1 5
CORP2 10
CORP3 5
SB 20
SB1 10
SB2 10
MID 10
LARGE 20
Simply change your existing GROUP BY to GROUPING SET:
SELECT
Coalesce(subregion, region) AS region,
Sum(column)
FROM mytable
GROUP BY GROUPING SETS(region, subregion)
HAVING Coalesce(subregion, region) IS NOT NULL
sounds like you need to aggregate the same table by different fields, but get both back as if it were one field. The solution that comes to mind is a UNION
select sum() as sum, REGION as sf from table group by REGION
union ALL
select sum() as sum, SUB_REGION as sf from table group by SUB_REGION;
Hope that helps
based on Dan's question below, I add, if you don't want to agg the vals, just take out the sum and group by and do the straight union
select REGION as sf from table
union ALL
select SUB_REGION as sf from table;
EDIT:
One more thought, perhaps when you do the query in the first place, you may want to look into the concept of ROLLUPs as an additional clause on your group bu and agg function, might help solve this in one shot.
Do the same group by query you're doing, but try using group by ROLLUP:
Something like (untested):
select region, subregion, sum(some_column) as sum
from some_table
group by rollup(region, subregion)
order by region, subregion;
Try using OLAP functions rollup and grouping like this:
select
nvl(subregion, region) region, sum("sum")
from t
group by region, rollup(subregion)
having case when count(*) = 1 then 0 else 1 end = grouping(subregion);
In the above,
having case when count(*) = 1 then 0 else 1 end = grouping(subregion);
The above excludes the rolluped row if there is only one row for that region so that there are no duplicates.
Also, avoid using reserved keywords such as sum or count in your identifiers.
Demo:
SQL> with t(REGION ,SUBREGION ,s) as (
2 select 'CORP' , 'CORP1' , 5 from dual union all
3 select 'CORP' , 'CORP2' , 10 from dual union all
4 select 'CORP' , 'CORP3' , 5 from dual union all
5 select 'SB' ,'SB1' ,10 from dual union all
6 select 'SB' ,'SB2' ,10 from dual union all
7 select 'MID' , null , 10 from dual union all
8 select 'LARGE' , null , 20 from dual
9 )
10 select
11 nvl(subregion, region) region, sum(s)
12 from t
13 group by region, rollup(subregion)
14 having case when count(*) = 1 then 0 else 1 end = grouping(subregion);
REGIO SUM(S)
----- ----------
SB1 10
SB2 10
SB 20
MID 10
CORP1 5
CORP2 10
CORP3 5
CORP 20
LARGE 20
9 rows selected.
SQL>

Using SQL to work out the average of some, but not all, records

I am trying to work out the SQL to average a series of numbers, but only to include those greater than 0.
For example:
Field
4
5
0
6
SELECT Avg(Field) FROM Table;
gives 3.75. But I want it to ignore the 0 so the average is 5.
SELECT Avg(Field) FROM Table where Field > 0;
works but what if I have more than 1 field:
Field1 Field2
4 2
5 0
0 3
6 4
SELECT Avg(Field1), Avg(Field2) FROM Table;
Using
SELECT Avg(Field1), Avg(Field2) FROM Table where Field1 >0 and Field2>0;
will not work
How do I do that? Note the numbers can be anything from 0 to 100
Just filter out 0 using the where clause.
SELECT Avg(Field) FROM Table Where Field > 0
You can use a conditional expression:
SELECT
Avg(case when Field1 > 0 then Field1 end),
Avg(case when Field2 > 0 then Field2 end)
FROM table
SELECT Avg(Field) FROM yourtable where Field > 0 ;
You will have to fake AVG() :):):)
SELECT SUM(Field1)/SUM(IF(field1>0, 1, 0)), SUM(Field2)/SUM(IF(field2>0, 1, 0))
I assume there is GROUP BY in the query
Convert the 0 to null like this:
SELECT AVG(IF(N=0,NULL,N)) FROM
(
SELECT 5 N
UNION ALL SELECT 4
UNION ALL SELECT 0
UNION ALL SELECT 2
) the_ns

SQL union same number of columns, same data types, different data

I have two result sets that look approximately like this:
Id Name Count
1 Asd 1
2 Sdf 4
3 Dfg 567
4 Fgh 23
But the Count column data is different for the second one and I would like both to be displayed, about like this:
Id Name Count from set 1 Count from set two
1 Asd 1 15
2 Sdf 4 840
3 Dfg 567 81
4 Fgh 23 9
How can I do this in SQL (with union if possible)?
My current SQL, hope this will better explain what I want to do:
(SELECT Id, Name, COUNT(*) FROM Customers where X)
union
(SELECT Id, Name, COUNT(*) FROM Customers where Y)
select *
from
(
SELECT 'S1' as dataset, Id, Name, COUNT(*) as resultcount FROM Customers where X
union
SELECT 'S2',Id, Name, COUNT(*) FROM Customers where Y
) s
pivot
(sum(resultcount) for dataset in (s1,s2)) p
You can do something like:
;WITH Unioned
AS
(
SELECT 'Set1' FromWhat, Id, Name FROM Table1
UNION ALL
SELECT 'Set2', Id, Name FROM Table2
)
SELECT
Id,
Name,
SUM(CASE FromWhat WHEN 'Set1' THEN 1 ELSE 0 END) 'Count from set 1',
SUM(CASE FromWhat WHEN 'Set2' THEN 1 ELSE 0 END) 'Count from set 2'
FROM Unioned
GROUP BY Id, Name;
SQL Fiddle Demo

one sql instead of 2 for counting

I have read a thread on this but when I tried it I can`t manage to make it work.
I want to count all the male and females from a table like so:
Select
count(case when substr(id,1, 1) in (1,2) then 1 else 0 end) as M,
count(case when substr(id,1, 1) in (3,4) then 1 else 0 end) as F
from users where activated=1
The ideea is that a user having an id starting with 1 or 2 is male
My table has 3 male entries and 2 are activated and it returns (the case statement doesn`t work)
M,F
2,2
Any input would be appreciated
id activated
123 1
234 0
154 1
You should use SUM instead. COUNT will count all non null values.
Select
SUM(case when substr(id,1, 1) in (1,2) then 1 else 0 end) as M,
SUM(case when substr(id,1, 1) in (3,4) then 1 else 0 end) as F
from users where activated=1
COUNT will give you the number of non-null values, whatever they are. Try SUM instead.
If your Oracle version is 10g or later, as an alternative, you can use regexp_count function. I assume that the ID column is of number data type, so in the example it explicitly converted to varchar2 data type using TO_CHAR function. If the data type of the ID column is varchar2 or char then there is no need of any type of data type conversion.
Here is an example:
SQL> create table M_F(id, activated) as(
2 select 123, 1 from dual union all
3 select 234, 0 from dual union all
4 select 434, 1 from dual union all
5 select 154, 1 from dual
6 );
Table created
SQL> select sum(regexp_count(to_char(id), '^[12]')) as M
2 , sum(regexp_count(to_char(id), '^[34]')) as F
3 from M_F
4 where activated = 1
5 ;
M F
---------- ----------
2 1
Demo

How to transpose recordset columns into rows

I have a query whose code looks like this:
SELECT DocumentID, ComplexSubquery1 ... ComplexSubquery5
FROM Document
WHERE ...
ComplexSubquery are all numerical fields that are calculated using, duh, complex subqueries.
I would like to use this query as a subquery to a query that generates a summary like the following one:
Field DocumentCount Total
1 dc1 s1
2 dc2 s2
3 dc3 s3
4 dc4 s4
5 dc5 s5
Where:
dc<n> = SUM(CASE WHEN ComplexSubquery<n> > 0 THEN 1 END)
s <n> = SUM(CASE WHEN Field = n THEN ComplexSubquery<n> END)
How could I do that in SQL Server?
NOTE: I know I could avoid the problem by discarding the original query and using unions:
SELECT '1' AS TypeID,
SUM(CASE WHEN ComplexSubquery1 > 0 THEN 1 END) AS DocumentCount
SUM(ComplexSubquery1) AS Total
FROM (SELECT DocumentID, BLARGH ... AS ComplexSubquery1) T
UNION ALL
SELECT '2' AS TypeID,
SUM(CASE WHEN ComplexSubquery2 > 0 THEN 1 END) AS DocumentCount
SUM(ComplexSubquery2) AS Total
FROM (SELECT DocumentID, BLARGH ... AS ComplexSubquery2) T
UNION ALL
...
But I want to avoid this route, because redundant code makes my eyes bleed. (Besides, there is a real possibility that the number of complex subqueries grow in the future.)
WITH Document(DocumentID, Field) As
(
SELECT 1, 1 union all
SELECT 2, 1 union all
SELECT 3, 2 union all
SELECT 4, 3 union all
SELECT 5, 4 union all
SELECT 6, 5 union all
SELECT 7, 5
), CTE AS
(
SELECT DocumentID,
Field,
(select 10) As ComplexSubquery1,
(select 20) as ComplexSubquery2,
(select 30) As ComplexSubquery3,
(select 40) as ComplexSubquery4,
(select 50) as ComplexSubquery5
FROM Document
)
SELECT Field,
SUM(CASE WHEN RIGHT(Query,1) = Field AND QueryValue > 1 THEN 1 END ) AS DocumentCount,
SUM(CASE WHEN RIGHT(Query,1) = Field THEN QueryValue END ) AS Total
FROM CTE
UNPIVOT (QueryValue FOR Query IN
(ComplexSubquery1, ComplexSubquery2, ComplexSubquery3,
ComplexSubquery4, ComplexSubquery5)
)AS unpvt
GROUP BY Field
Returns
Field DocumentCount Total
----------- ------------- -----------
1 2 20
2 1 20
3 1 30
4 1 40
5 2 100
I'm not 100% positive from your example, but perhaps the PIVOT operator will help you out here? I think if you selected your original query into a temporary table, you could pivot on the document ID and get the sums for the other queries.
I don't have much experience with it though, so I'm not sure how complex you can get with your subqueries - you might have to break it down.