Display count 0 values in SQL Server - sql

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.

Related

When duplicate in 1 column, get row with highest value

a Query results in something like the example below:
col1 col2
A 0
B 0
B 1
C 0
D 1
Now I want no duplicates in col1. but when col1 has duplicates it should give the row where col2 = 1 (or highest value) and don't give the row where col2 = 0. So the result will be:
col1 col2
A 0
B 1
C 0
D 1
How should this query look like?
EDIT:
max works, but there is a thirth colomn, with some text value when col2 = 1
How do I get there result on the right? So when there is duplicate in col1, then get the row where col2 = 1
col1 col2 col3 col1 col2 col3
A 0 A 0
B 0 B 1 XYZ
B 1 XYZ --> C 0
C 0 D 1 YXA
D 1 YXA
Thanks!
Check out the MAX() function: https://learn.microsoft.com/en-us/sql/t-sql/functions/max-transact-sql?view=sql-server-2017
SELECT col1,MAX(col2)
FROM [yourTable]
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

How to generate Query aggregation in oracle?

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.

SQL Compare grouped values

If we have a table like:
col1 | col2
-----------
A | 1
B | 2
A | 1
C | 16
B | 3
How it can be determined if the all rows for given value in col1 are the same?
For example, here whe have only '1's for A, but for B we have '2' and '3'.
Something like:
A | true
B | false
C | true
select col1, case when count(distinct col2) = 1
then 'true'
else 'false'
end as same_col2_results
from your_table
group by col1
I have a preference for using min() and max() for this purpose, rather than count(distinct):
select col1,
(case when min(col2) = max(col2) then 'true' else 'false' end) as IsCol2Same
from table t
group by col1;
Then comes the issue of NULL values. If you want to ignore them (so a column could actually have two values, NULL and another value), then the above is fine (as is count(distinct)). If you want to treat NULL the same way as other values, then you need some additional tests:
select col1,
(case when min(col2) is null then 'true' -- All NULL
when count(col2) <> count(*) then 'false' -- Some NULL
when min(col2) = max(col2) then 'true' -- No NULLs and values the same
else 'false'
end) as IsCol2Same
from table t
group by col1;
Select distinct(t1.col1), case when t1.col2=t2.col2 then TRUE else FALSE end
from table t1, table t2 where t1.col1=t2.col2

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