SQL, count in multiple columns then group by - sql

I am trying to count in multiple columns then group by for a total sum where the same data appears in any column
Source data table:
P1 P2 P3
-----------
a b
a a a
b c
a b b
b a
I want it to show something like this:
Desired query output:
Total
-------------
a | 6
b | 5
c | 1

You can use a union query
SELECT x.f1,Count(x.f1) FROM
(SELECT p1 As F1 FROM table
UNION ALL
SELECT p2 As F1 FROM table
UNION ALL
SELECT p3 As F1 FROM table) x
GROUP BY x.f1

You can union all the records in a subquery and on the outer query, count each value.
SELECT b.a, COUNT(b.a)
FROM
(
SELECT P1 a
FROM tableName
UNION ALL
SELECT P2 a
FROM tableName
UNION ALL
SELECT P3 a
FROM tableName
) b
GROUP BY b.a

Related

Recursive query to retrieve all child from given id

I am migrating from oracle to postgres and I don't know how to make a recursive query
Here is an example data set:
id
id_parent
name
1
0
aa
2
0
aa
3
1
aa
4
3
aa
5
3
aa
6
2
aa
7
6
aa
For id = 3, I want to get
id
3
4
5
for id =1
id
1
3
4
5
with this I have all but I don't know how to filter by id:
SELECT id FROM (
with recursive cat as (
select * from table
union all
select table.*
from table
join cat on cat.id_parent = table.id
)
select * from cat order by id
)
as listado where id != '0' group by id
There is no need of using sub-query. You just need to fix your recursive query only as -
WITH RECURSIVE cat (id, id_parent) as
(
SELECT id, id_parent
FROM table
WHERE id = 1
UNION ALL
SELECT d.id, d.id_parent
FROM table d
JOIN cat ON cat.id = d.id_parent
)
SELECT id
FROM cat
ORDER BY id;
Demo.

Count distinct by link on sql?

I'm trying to count distinct by the link between two columns.
Here is the example.
rownum
type
id
1
A
a
2
A
b
3
B
b
4
B
c
5
C
c
6
C
d
If I count distinct by type column, it returns 3. However, what I'd like to do is to consider rownum 2 and 3, 4 and 5 are not distinctive because they got the same value on id column.
To rephrase,
type
array of id
A
a, b
B
b, c
C
c, d
Since A and B got same b, and B and C got same c on their arrays, it would return 1 as a result.
I have no idea where to start. Would appreciate if I can get any hint or something.
Consider below:
you might use STRING_AGG
WITH TMP_TBL AS
(
SELECT 1 AS ROWNUM, 'A' AS TYPE, 'a' AS ID UNION ALL
SELECT 2,'A','b' UNION ALL
SELECT 3,'B','b' UNION ALL
SELECT 4,'B','b' UNION ALL
SELECT 5,'C','c' UNION ALL
SELECT 6,'C','d'
);
SELECT DISTINCT TYPE,N_ID
FROM
(
SELECT TYPE,STRING_AGG(ID)OVER(PARTITION BY TYPE) AS N_ID FROM TMP_TBL
)

Get Count of records - Oracle

I'm trying to get count of records from table by joining 2 or more table. Suppose I have 3 table like follows,
Table A
Column 1 Column 2
121 XX
123 XX
124 A0
125 A2
126 XX
Table B
Column 1
A0
A1
A2
A3
Table C
Column 1 Column 2
121 A0
122 A1
123 A0
124 A0
125 A2
126 A3
From these I need count result as follows,
Column 1 Column 2
XX,A0 2
XX,A1 0
XX,A2 0
XX,A3 1
A0,A0 1
A1,A1 0
A2,A2 1
A3,A3 0
Here I have 121 and 123 with XX in table A and same 121,123 in table C with A0, so count should be 2. Similarly 124 have A0 in table A and A0 in table C, so count should 1 and if no record matched with any column 2 it should have 0.
I tried with below query it is not returing as expected,
select b.column2 ||','|| c.column2 column , count(a.column1) count
from table A a
join table c c
on a.column1=c.column1
join table b b
on b.column1=c.column2
group by b.column2 ||','|| c.column2
order by b.column2 ||','|| c.column2
first you would want a cartesian product to get the set of all possible combinations betweeen tablea and tableb. I changed the column names to something more readable.
create table tablea(id int, name varchar2(10));
create table tableb(name varchar2(10));
create table tablec(id int, name varchar2(10));
insert into tablea
select 121,'XX' from dual union all
select 123,'XX' from dual union all
select 124,'A0' from dual union all
select 125,'A2' from dual union all
select 126,'XX' from dual
insert into tableb
select 'A0' from dual union all
select 'A1' from dual union all
select 'A2' from dual union all
select 'A3' from dual
insert into tablec
select 121,'A0' from dual union all
select 122,'A1' from dual union all
select 123,'A0' from dual union all
select 124,'A0' from dual union all
select 125,'A2' from dual union all
select 126,'A3' from dual
--Gets all possible combination of tablea and tableb
select distinct a.name as a_name,b.name as b_name
from tablea a
join tableb b
on 1=1
Then you would do a group by on these combination fields as follows
with data
as (select distinct a.name as a_name,b.name as b_name
from tablea a
join tableb b
on 1=1
)
,tablec_data
as (select c.name c_name,a.name a_name
from tablec c
join tablea a
on c.id=a.id
)
select max(m.a_name||','||m.b_name) as val_name,count(n.c_name) as cnt
from data m
left join tablec_data n
on m.a_name=n.a_name
and m.b_name=n.c_name
group by m.a_name,m.b_name
order by m.a_name desc,m.b_name
Here is a db fiddle link
https://dbfiddle.uk/?rdbms=oracle_18&fiddle=9e573822ecc1087e5871c80b586d1116
+----------+-----+
| VAL_NAME | CNT |
+----------+-----+
| XX,A0 | 2 |
| XX,A1 | 0 |
| XX,A2 | 0 |
| XX,A3 | 1 |
| A2,A0 | 0 |
| A2,A1 | 0 |
| A2,A2 | 1 |
| A2,A3 | 0 |
| A0,A0 | 1 |
| A0,A1 | 0 |
| A0,A2 | 0 |
| A0,A3 | 0 |
+----------+-----+
Table A should be used instead of Table B for combining the values. Table B doesn't have column Colunn2.
Also, Remember alias name for a.column2 ||','|| c.column2 should not be column as this is reserved keyword in oracle. So you can use column2 or something else.
EDIT: Following will give 0 count for not matched records.
select t1.column2,
case when t2.count1 is not null then t2.count1 else t1.count1 end as count1
from (
(select distinct a.column2||','||b.column1 as column2,
0 as count1 from tableA a join tableB b on a.column2='XX'
union
select distinct c.column2||','||b.column1 as column2,
0 as count1 from tableC c join tableB b on c.column2=b.column1
)t1
left join
(select a.Column2 ||','|| c.Column2 as column2,
count(*) count1 from TableA a join TableC c on a.column1=c.column1
join TableB B on b.column1=c.column2 group by a.column2 ||','|| c.column2
)t2
on t1.column2=t2.column2
)
order by
t1.column2
Output:
A0,A0 1
A1,A1 0
A2,A2 1
A3,A3 0
XX,A0 2
XX,A1 0
XX,A2 0
XX,A3 1
At first prepare key columns, use simple union. Then use this keys to construct join. Left join is used because we need zeros too:
with keys as (select 'XX' ka, column1 kb from b union all select column1, column1 from b)
select ka, kb, sum(case when c.column2 is not null then 1 else 0 end) cnt
from keys
left join a on ka = a.column2
left join c on kb = c.column2 and a.column1 = c.column1
group by ka, kb
order by ka, kb
dbfiddle demo

Getting all the values in one query that aren't in another with a group by

Given that I am using Redshift, how would I get the counts for a query that asks:
Given table A and table B, give me all the count of values in Table A for that grouping that aren't in table B;
So if table A and B look like:
Table A
Id | Value
==========
1 | "A"
1 | "B"
2 | "C"
And table B:
Id | Value
==========
1 | "A"
1 | "D"
2 | "C"
I would want:
Id | Count
==========
1 | 1
2 | 0
You can use left join and group by:
select a.id, sum( (b.id is null)::int )
from a left join
b
on a.id = b.id and a.value = b.value
group by a.id;
Use except and subquery
with a as
(
select 1 as id, 'A' as v
union all
select 1,'B'
union all
select 2,'C'
),b as
(
select 1 as id, 'A' as v
union all
select 1,'D'
union all
select 2,'C'
), c as
(
select id,v from a except select id,v from b
)
select id,sum ( (select count(*) from c where c.id=a.id and c.v=a.v))
from a group by id
output
id cnt
1 1
2 0
online demo which will work in redshift

How to select the total count?

I have the following two tables (postgresql)
tableA
a b
----------
1 A
2 B
table B
c b
----------
1 A
3 B
I want to find out the same number of columns b, but if column a and column c are the same, count one.
So the final result should be
b count
----------
A 1
B 2
How should I write sql?
You need union all for the 2 tables and then group by b to count distinct values of a:
select t.b, count(distinct t.a) counter
from (select * from tablea union all select * from tableb) t
group by t.b
Aggregate by column b and take the distinct count of column a:
SELECT b, COUNT(DISTINCT a) AS count
FROM yourTable
GROUP BY b
ORDER BY b;