How to generate Query aggregation in oracle? - sql

I am working on some code, sample table shown below. Looking for aggregated output to some query
Sample Table
col1 col2
---- ----
val1 Fully
val1 Partial
val2 NoService
val2 Partial
val3 Fully
val3 NoService
val3 Fully
val3 Partial
val1 Fully
val2 NoService
Output expected
Col1 Fully Partial NoService Total
---- ----- ------- --------- -----
val1 2 1 0 3
val2 0 1 2 3
val3 2 1 1 4
Not sure how to do this in oracle? please some one help

Try This: It's not a dynamic solution though it will provide the result what you expect. If you have fixed values in val2 then it's the best one otherwise you have to choose dynamic way.
SELECT col1,
SUM(CASE WHEN col2 = 'Fully' THEN 1 ELSE 0 END) Fully,
SUM(CASE WHEN col2 = 'Partial' THEN 1 ELSE 0 END) Partial,
SUM(CASE WHEN col2 = 'NoService' THEN 1 ELSE 0 END) NoService,
COUNT(col2) total
FROM yourTable
GROUP BY col1

In Oracle, you can do this using pivot or aggregate function with CASE:
SELECT COL1,
COUNT(CASE when COL2 = 'FULLY' THEN 1 ELSE 0 END) AS FULLY,
COUNT(CASE when COL2 = 'PARTIAL' THEN 1 ELSE 0 END) AS PARTIAL
FROM TABLE_A A
LEFT JOIN TABLE_A B
on B.COL1 = A.COL1
GROUP BY COL1

Try this using pivot query function in oracle
select * from(select nvl(col1,'Total') col1,nvl(col2,'Total') col2,count(1) cnt from mytable group by CUBE(col1,col2))
pivot
(
sum(cnt)
for col2 IN
(
'Fully' AS "Fully",
'Partial' AS "Partial",
'NoService' AS "NoService",
'Total' As "Total"
)
)
here from above query i can get both column and row total.
use query as per your need.

Related

how to output result of group by of two columns with one column values as row and another as columns?

I have table like this
id col1 col2
1 A 1
2 B 0
3 A 1
4 C 1
5 B 0
6 A 0
7 C 1
8 C 1
9 B 1
10 B 0
I need a query something like this
Values 1 0
A 2 1
B 1 3
C 3 0
In the above result the header shows the col2 distinct values (1,0) and rows names represents distinct values of col1. The values in the table shows the counts.
Any suggestion to get the result like this in postgresql?
You need conditional aggregation :
select col1,
sum(case when col2 = 1 then 1 else 0 end) as 1,
sum(case when col2 = 0 then 1 else 0 end) as 0
from table t
group by col1;
You could also use FILTER:
SELECT
col1,
COUNT(*) FILTER (WHERE col2 = 1) AS 1,
COUNT(*) FILTER (WHERE col2 = 0) AS 0,
FROM
foo
GROUP BY
col1;
Here are simpler ways to write this logic. The first is Postgres-specific:
select col1,
sum( (col2 = 1)::int ) as num_1,
sum( (col2 = 0)::int as num_0
from t
group by col1;
The second just uses arithmetic:
select col1,
sum( col2 ) as num_1,
sum( 1 - col2 ) as num_0
from t
group by col1;

SQL : MAX() OVER (PRITITON BY ... ORDER BY ..) : ORDER BY Clause is working looks like

I am trying to use MAX(case when col4='ABC' then col1 else 0 end) OVER (PARTITION BY col2 order by **col3**)
col1~col2~col3~col4
30 A B1 ABC
35 A A1 ABC
36 A NULL NULL
40 A X1 ABC
50 B M1 ABD
but I am getting the result as 40, but I want 35 as my result. It looks like
order by col3
is not getting applied before MAX aggregate. Is there any other way?
I can't write the row_number() in where clause, as we are trying to create columns and there are many columns and complicated logic around it.
Currently I am trying it in Teradata, but actually it will be implemented in HIVE.
This is too long for a comment. For this expression:
MAX(case when col4 = 'ABC' then col1 else 0 end) OVER (PARTITION BY col2 order by col3)
You should be getting:
col1~col2~col3~col4
30 A A1 ABC 30
40 A X1 ABC 40
50 B M1 ABD 0
If you want "30" for all, you might consider:
min(case when col4 = 'ABC' then col1 end) over ()
PARTITION BY will aggregate on distinct col2 values. Therefore, the MAX() value of the three col2 'A' values is 40.
If you want to return '35'. This is suggesting that A1 is the first row returned in the partition. First_Value() could be used to return the first row in the partition group.
FIRST_VALUE(CASE WHEN col4 = 'ABC' THEN col1
ELSE 0 END) OVER (PARTITION BY col2 order by col3)
EDIT: Have moved to window function in sub query to get correct row
Sample data (as table variable)
declare #t table(col1 int,col2 char(1),col3 char(2),col4 char(3))
insert #t values (30,'A','B1','ABC')
,(35,'A','A1','ABC')
,(36,'A',NULL,NULL)
,(40,'A','X1','ABC')
,(50,'B','M1','ABD')
Query using row_number() to get row to join to
select t.*, mx
from #t t
join (
select
col2,
case when col4='ABC' then col1 else 0 end as mx,
row_number() over (PARTITION BY col2 order by case when col3 is null then 1 else 0 end, col3) rn
from #t
) m on m.col2=t.col2 and rn=1
Result:
col1 col2 col3 col4 col2 mx
30 A B1 ABC A 35
35 A A1 ABC A 35
36 A NULL NULL A 35
40 A X1 ABC A 35
50 B M1 ABD B 0

Pivot table in teradata sql

I have data like this:
ID Result
1 value1
2 value1
2 value2
3 value1
4 value1
4 value2
4 value3
How can I accomplish in teradata SQL the pivot table like in Excel.
ID Value1 Value2 ...
1 count of Value1 for ID 1 count of Value2 for ID 1 ...
2 count of Value1 for ID 2 count of Value2 for ID 1 ...
3 ... ... ...
assuming that there is a large number of ID and varying number of Values.
SELECT sum(case when Result='Value1' then ID end) "Value1"
, sum(case when Result='Value2' then ID end) "Value2"
FROM your_table
GROUP BY null;
Not much context can be added here I'm afraid, except this is the way pivots can be implemented in TD up to v15.x
So i found the answer and i would like to share it with you
First of all you need to recalculate the data to know the counts for id||Value
CREATE TABLE myTable_count as (
SELECT ID, Result, count(1) as countOfResult
FROM myTable
group by ID, Result
) WITH DATA
Then you can do a pivot, but you have to know the names of result's
SELECT ID,
sum(CASE WHEN Result='Value1' then countOfResult else NULL END) Value1,
sum(CASE WHEN Result='Value2' then countOfResult else NULL END) Value2
FROM myTable_count
GROUP BY ID;
If it help you give it a vote up.
SELECT
id,
count(
CASE WHEN result1 = 'value1' THEN id END
) AS value1,
COUNT(
CASE WHEN result1 = 'value2' THEN id END
) AS value2,
COUNT(
CASE WHEN result1 = 'value3' THEN id END
) as value3
FROM
pivot_tb1
group by
1;

Display count 0 values in SQL Server

TableA has the data as follows:
Col1 Col2 Col3
001 A 0
001 B 0
002 C 0
003 D 0
I want to see the count of records group by Col1 and Col2 where Col3 = 1
May be the query as follows:
Select Col1, Col3, Count(1)
From TableA
Group By Col1, Col2
Where Col3 = 1
Since there are no records with Col3 = 1 no records will be displayed, but I still want to display the values with count as 0.
For example the output is as follows:
Col1 Col2 CountOfRecords
001 A 0
001 B 0
002 C 0
003 D 0
Could you please help me to get output as shown above.
One approach would be to use conditional aggregation:
Select Col1, Col2, Count(case when Col3 = 1 then 1 end) as CountOfRecords
From TableA
Group By Col1, Col2
firstly you write wrong sql statement, you can not use Where clause after Group by clause.. you need to use before group by.. if you want to use filter after group by use Having clause..
second if there is no matching column for 'Col3 = 1' then you did not get any result.. for that you need to use case statement or sub queries.
otherwise do not use group by clause rather than use simple sql statement.

SQL GROUP BY with a SUM CASE statement

I know that there are a lot of question like this:
SQL GROUP BY CASE statement with aggregate function
but I've tried doing:
with T as (select col1 , SUM(CASE WHEN col2 = 1 THEN col3 ELSE 0 END) AS Totale
from tabella
group by col1, col2)
select col1, Totale
from T
group by col1, Totale
but I'm getting
col1 | Totale
---------------
1 0
1 70
2 0
2 90
Instead of:
col1 | Totale
---------------
1 70
2 90
What's wrong with that?
UPDATE:
My bad, I try to keep it simple but I've overdone it.. What I've to do is:
with T as (select col1 , SUM(CASE WHEN col2 = 1 THEN col3 ELSE 0 END) AS TotaleA,
SUM(CASE WHEN col2 = 2 THEN col3 ELSE 0 END) AS TotaleB,
(...)
from tabella
group by col1, col2)
select col1, TotaleA, TotaleB
from T
group by col1, TotaleA, TotaleB
And the solution is to do without col2 in the grouping... I was afraid getting "invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause", but it's not.. Can I mark a comment as the correct answer?
You can also approach this problem by using a subquery:
SELECT
col1,
SUM(A) TotalA,
SUM(B) TotalB
FROM
(
select col1,
CASE WHEN col2 = 1 THEN col3 ELSE 0 END A,
CASE WHEN col2 = 2 THEN col3 ELSE 0 END B
from tabella
) t
GROUP BY Col1
Here is one idea. Not sure why you have this wrapped in a cte but why not make it simpler?
select col1
, SUM(col3) AS Totale
from tabella
where col2 = 1
group by col1