Group BY on Condition basis - sql

I have data in following way....
ColumnA ColumnB
7675 22838
7675 24907
7675 NULL
I want the results in following way.....
ColumnA ColumnB
7675 2 (need total count for Not Null value)
7675 0 (need count 0 for NULL value)

SELECT ColumnA, COUNT(ColumnB) ColumnB
FROM YourTable
GROUP BY ColumnA
UNION ALL
SELECT ColumnA, 0
FROM YourTable
WHERE ColumnB IS NULL
GROUP BY ColumnA

You could introduce a calculated column indicating whether ColumnB is null or not and use it as a grouping criterion together with ColumnA:
SELECT
t.ColumnA,
ColumnB = COUNT(t.ColumnB)
FROM
dbo.YourTable AS t
CROSS APPLY
(SELECT CASE WHEN t.ColumnB IS NULL THEN 1 ELSE 0 END) AS x (SubGroup)
GROUP BY
t.ColumnA,
x.SubGroup
ORDER BY
t.ColumnA,
x.SubGroup
;
The COUNT(t.ColumnB) expression would always be NULL for a null subgroup, and for the corresponding non-null subgroup it would return the number of the non-null entries.

select columnA,
count(columnB) as non_null_count,
sum(columnB is null) as null_count
from your_table
group by ColumnA

you could easily do with a count and sum which may be faster if there are a lot of rows rather than selecting all of the rows twice with a UNION
SELECT columna, columnb, SUM(mycount)
FROM
( SELECT *, COUNT(columnb) as mycount
FROM test
GROUP BY columnb
)t
GROUP BY mycount
ORDER BY CASE WHEN mycount = 0 THEN 1 ELSE 2 END DESC;
Fiddle Demo

Related

How to create a pivot table in PostgreSQL

I am looking to essentially create a pivot view using PostgreSQL, such that the table below:
Column A
Column B
Happy
Sad
Sad
Happy
Happy
Sad
becomes
Count
Column A
Column B
Happy
2
1
Sad
1
2
I've been able to use case/when operators far enough such that I can see the counts under independent columns,
SELECT
COUNT(CASE WHEN column1 = 'Happy' THEN 1 END) AS column1_Happy_count,
COUNT(CASE WHEN column1 = 'Sad' THEN 1 END) AS column1_Sad_count,
COUNT(CASE WHEN column2 = 'Happy' THEN 1 END) AS column2_Happy_count,
COUNT(CASE WHEN column2 = 'Sad' THEN 1 END) AS column2_Sad_count,
COUNT(CASE WHEN column3 = 'Happy' THEN 1 END) AS column3_Happy_count,
COUNT(CASE WHEN column3 = 'Sad' THEN 1 END) AS column3_Sad_count
FROM your_table;
but am missing the step to essentially each the pair of columns vertically.
I'm unable to use extensions such as tablefunc and crosstab.
Try this:
CREATE TABLE my_table (
column_a varchar(10),
column_b varchar(10)
);
INSERT INTO my_table (column_a, column_b)
VALUES ('Happy', 'Sad'),
('Sad', 'Happy'),
('Happy', 'Sad'),
('Good', 'Bad');
WITH DataSource (col, val) AS
(
SELECT 'a', column_a
FROM my_table
UNION ALL
SELECT 'b', column_b
FROM my_table
)
SELECT uniq.val AS "Count"
,MAX(case when counts.col = 'a' then counts end) AS "Column A"
,MAX(case when counts.col = 'b' then counts end) AS "Column B"
FROM
(
SELECT DISTINCT val
FROM DataSource
) uniq
INNER JOIN
(
SELECT col
,val
,COUNT(*) counts
FROM DataSource
GROUP BY col
,val
) counts
ON uniq.val = counts.val
GROUP BY uniq.val
will give you this:
You may aggregate for ColumnA, aggregate for ColumnB then do a full join as the following:
select coalesce(A.ColumnA ,B.ColumnB) as "Count",
A.cnt as "Column A",
B.cnt as "Column B"
from
(
select ColumnA, count(*) cnt
from tbl_name
group by ColumnA
) A
full join
(
select ColumnB, count(*) cnt
from tbl_name
group by ColumnB
) B
on A.ColumnA = B.ColumnB
If the distinct values in ColumnA are the same as the distinct values of ColumnB then you can use join instead of the full join.
See demo.

Grouping by one column and counting from multiple columns

I am trying to write a query on the below scenario
Result
Example:
ColumnA ColumnB
A B
B C
Result:
ColumnA countB countC
A 1 0
B 0 1
From your sample data, no aggregation is needed:
SELECT columnA,
(CASE WHEN columnB = 'B' THEN 1 ELSE 0 END) as countB,
(CASE WHEN columnB = 'C' THEN 1 ELSE 0 END) as countC
FROM t;
It should work:
Select
columnA,
count(ColumnB) as ColumnB,
count(ColumnC) as ColumnC
From Table
Group By
columnA
There is not enough sample data to confirm that, but based also on the title of your question you seem to be looking for condition aggregation :
SELECT
columnA,
COUNT(CASE WHEN columnB = 'B' THEN 1 END) countB,
COUNT(CASE WHEN columnB = 'C' THEN 1 END) countC
FROM mytable
GROUP BY columnA
Assuming that your real scenario is larger that that, I think that is better to use a pivot
DECLARE #table TABLE(ColumnA CHAR(1), ColumnB CHAR(1))
INSERT #table VALUES ('A', 'B')
INSERT #table VALUES ('B', 'C')
SELECT ColumnA, A AS CountA, B AS CountB, C AS CountC, D AS CountD....
FROM
(
SELECT ColumnA, ColumnB
FROM #table
) AS Source
PIVOT
(
Count(ColumnB)
FOR ColumnB IN ([A], [B], [C], [D].....)
) AS Pvt

Is it possible to use a subselect in a CASE expression with db2?

I'm trying to run the below query on a db2 database.
SELECT
columnA,
(CASE
WHEN columnA NOT IN (SELECT DISTINCT columnC FROM table_2) THEN 1 ELSE 0
END) AS columnB
FROM
table_1;
This is producing the error SQL0115 - Comparison operator NOT not valid. There are no errors if I replace the subselect with values that I know it will produce.
SELECT
columnA,
(CASE
WHEN columnA NOT IN ('ABC', 'EFG') THEN 1 ELSE 0
END) AS columnB
FROM
table_1;
Is it possible to use a subselect for a CASE expression with db2?
Your code should be fine, but the distinct is not necessary:
SELECT columnA,
(CASE WHEN columnA NOT IN (SELECT columnC FROM table_2) THEN 1 ELSE 0
END) AS columnB
FROM table_1;
I would, however, write it using NOT EXISTS:
SELECT columnA,
(CASE WHEN NOT EXISTS (SELECT 1 FROM table_2 t2 WHERE t2.columnC = t1.columnA)
THEN 1 ELSE 0
END) AS columnB
FROM table_1 t1;
NOT IN will not work as you expect when any of the values returned by the subquery are NULL.
You can also move the logic to the FROM clause:
SELECT columnA,
(CASE WHEN t2.columnC IS NOT NULL THEN 1 ELSE 0
END) AS columnB
FROM table_1 t1 LEFT JOIN
(SELECT DISTINCT columnC
FROM table_2
) t2
ON t2.columnC = t1.columnA

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

advice needed for SQL query

Can some one help to provide the SQL query should be used to pull out the "columna" value which has max number "columnb" value as "Active". Means in columnb there is a value "Active" , I want to pull the columna value which has max of value Active n columnb.
I am looking output to be columna = M1 and Count = 4
columna columnb
M1 Active
M1 Active
M1 Active
M1 Active
M2 failed
M2 failed
M2 failed
M3 pending
M3 pending
M3 pending
The results you request would be produced by:
SELECT columna,COUNT(*)
FROM Table
WHERE columnb = 'Active'
GROUP BY columna
SELECT top 1 columna,COUNT(*) as cnt
FROM Table1
WHERE columnb = 'Active'
GROUP BY columna
order by cnt desc
FIDDLE
SELECT columna,count(*) FROM TABLE_NAME where columnb = "Active" GROUP BY columna
Syntax is slightly different between RDMBS-es, but logic remains. Filter your rows based on columnb, group them by columna, order them on count(*) and select top 1
SQL Server:
SELECT TOP 1 columna, COUNT(*) AS Count
FROM YourTable
WHERE columnb = 'Active'
GROUP BY columna
ORDER BY COUNT(*) DESC
SQLFiddle DEMO
MySQL:
SELECT columna, COUNT(*) AS Count
FROM YourTable
WHERE columnb = 'Active'
GROUP BY columna
ORDER BY COUNT(*) DESC
LIMIT 1
SQLFiddle DEMO