Agreggating multiple category columns in postgreSQL - postgresql

I have this table in my postgreSQL db that I need to aggregate in categories.
The table called "table1" looks like this
Column A
Column B
Column C
Apple
Volks
200
Apple
Volks
350
Lime
BMW
200
Apple
BMW
200
Lime
BMW
400
I want the output to look like this:
Column A
Column B
Column C
Apple
Volks
550
Apple
BMW
200
Lime
BMW
600
I've tried using groupby and sum(Column C) but it didn't worked out.
SELECT distinct Column A, Column B, sum(Column C) as "Sum of C"
GROUP BY Column A, Column B, Column C
FROM public.table1

You should not be aggregating and grouping the same column, and distinct is irrelevant given a group by already results in distinct groups; your syntax is also wrong, that query would result in an error as From must precede Group By.
However you can use distinct in an aggregation, like so:
SELECT Column_A, Column_B, sum(distinct Column_C) as "Sum of C"
FROM public.table1
GROUP BY Column_A, Column_B;

Related

JPA equivalent of PostgreSQL with null comparison

I have a requirement something like there are two db tables A and B.
Table A and table B both have column 'merit' of type integer. The requirement is to find the entries from table A those have merit that matches with the least merit number in table B.
If merit in B is NULL for all the entries, the query should result all the entries from table A.
If merit in B has valid numbers, the query should result the entries of A those match the least merit number in table B.
Sample data is like this::
TABLE A TABLE B
COL1 COL2 MERIT COL1 COL2 MERIT
a ab 1 c ac 1
b bc 2 d ad 3
From above data the least merit in B is 1 so, only the matching entry should result from Table A.
If merit column in B is null for all the entries ie. B has no valid number for merit, two entries from A should result.
So, I came up with the below sql query::
select A.* from A where A.merit IS NOT DISTINCT FROM (
select min(B.merit) from B where B.merit IS NOT NULL);
I am unable to write the JPA equivalent of this sql because of "IS NOT DISTINCT FROM".
The below queries are not working.
select a from A a where a.merit in (select min(b.merit) from B b where b.merit is not null)
select a from A a where a.merit = (select min(b.merit) from B b where b.merit is not null)
My environment is POSTGRESQL, HIBERNATE in QUARKUS.
Thanks for any suggestions.

Postgresql multiple queries or case

Suppose I have a two tables like
Id date1. date2. status. code
1. .... ........ 1. AB110
2. ....... ..... 2. AB001
3. ....... ....... 1. AB120
4. ...... ........ 1. AB111
And table2
Code. Name. Display
AB110 Abc. Y
AB001 Xyx. Y
I want something like this:
withdate. type1. type2. code. name
2 1. 1 AB110. Abc
1. 2. 3 AB001. Xyz
3. . 1. 2 AB120. Lol
1. 1 5 AB111. Zzz
Select code,
table2.name,
count(case when date1 is not null then id) as withdate,
count(case when status=1 then id) as type1,
count(case when status=2 then id) as type2
from table, table2
where table.code=table2.code
group by code, name
Is it rigth to write a query like this ?
Yes it is right to write a query like that. The logic is good, but there is a synthax error in the case. I will prefer you count using the sum aggregate function as below.
select code,
table2.name,
sum(date1 is not null) as withdate,
sum(status=1) as type1,
sum(status=2) as type2
from table, table2
where table.code=table2.code
group by code, name;
This way when date1 is not null 1 is added to the cummated value of the sum else zero is added which is like counting.
Your query looks correct to me, except for the fact you forgot to fully qualify you column names and forgot the end keywords in the case expressions. There are, however, some improvements you could perform.
First, you shouldn't use implicit joins (having more than one table in the from clause) - they have been considered deprecated for quite a few years, and you should use a join clause.
Second, you didn't mention what version you were using, but Postgres 9.4 introduced a filter clause that can save you some of the boiler-plate of those case expressions.
SELECT table1.code,
table2.name,
COUNT(*) FILTER (WHERE date1 IS NOT NULL) AS withdate,
COUNT(*) FILTER (WHERE status = 1) AS type1,
COUNT(*) FILTER (WHERE status = 2) AS type2
FROM table1
JOIN table2 ON table1.code = table2.code
GROUP BY table1.code, table2.name

sum of values from 3 tables

I have 3 tables:
table A: building_id, region_code
table B: building_id, storey_no
table C: building_id, storey_no, room_no
What query would calculate sum of room numbers for all the buildings in each region with number of storeys in certain range (below is the sample query which doesn't work as I don't know how to include table B in it with the condition on number of storeys, etc.)?
SELECT SUM(C.room_no) AS room_sum, A.building_id
FROM A,B,C
WHERE A.region_code=1
AND A.building_id=C.building_id
AND B.storey_no>3
AND B.storey_no<10
GROUP BY C.building_id,C.room_no
Try joining on building_id from all three tables as below:
SELECT SUM(C.room_no) AS room_sum, C.building_id
FROM A INNER JOIN B
ON A.building_id = B.building_id
INNER JOIN C
ON A.building_id = C.building_id
WHERE A.region_code=1
AND B.storey_no>3
AND B.storey_no<10
GROUP BY C.building_id

postgresql--- add new column in table 1 by comparing with table 2

table 1 has columns (with rows as) like
date product comment
12.01.2014 1201/sm/pb yes
13.01.2014 1202/sa/pa no
14.01.2014 1215/ja/pc yes
table 2 has columns (with rows as) like
certificate name
1201 pencil
1202 pen
1215 parker
i want add one column (name) in table 1
date product comment name
12.01.2014 1201/sm/pb yes pencil
13.01.2014 1202/sa/pa no pen
14.01.2014 1215/ja/pc yes parker
some one please tell me how can i add a column in which rows should satisfy the
condition (product.table1 = certificate.table2 ==> name in table1)
thank u
You need to join the tables on the prefix of the product column.
select t1.date, t1.product, t1.comment, t2.name
from table_1 t1
joint table_2 t2 on left(t1.product, strpos(t1.product,'/') - 1) = t2.certificate;

PostgreSQL- Adding "TOTAL" row with more than one Group by columns

I was following this topic:
PostgreSQL - making first row show as total of other rows
..and i used this query to accomplish something similar in my code:
with w as ( select fruits, sum(a) a, sum(b) b, sum(c) c
from basket
group by fruits )
select * from w union all select 'total', sum(a), sum(b), sum(c) from w
It works fine but i now need to put two more columns before the sum columns simliar to the fruit one and i'm getting an error :
"... must appear in the GROUP BY clause or be used in an aggregate function"
Any help on how to do like the example above but with to more columns like "fruit"?
(Sorry my rep didn't let me continue the previous topic)
It was an easier fix than i thought.
with w as ( select fruits, vegetables, cereals, sum(a) a, sum(b) b, sum(c) c
from basket
group by fruits, vegetables, cereals )
select * from w union all select 'total', null, null, sum(a), sum(b), sum(c) from w
Two nulls in the last select solved the problem
what you need is something called "Grouping sets". The magic word here is ROLLUP, which is currently not yet supported by PostgreSQL. I guess it will be in 9.5. For now you have to continue on the path you have chosen (= subselects, CTEs, etc.).
a guy called atri shama is currently working on the stuff you really want. sorry for the bad news for now.