sum of values from 3 tables - postgresql

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

Related

Compare two string arrays in PostgreSQL

In a Postgres DB, I have 2 varchar[] columns in 2 tables with common ID that contain data as below:
I need to return rows where all values of t_col are present in f_col (with or without extra data).
Desired result:
I tried with the below as conditions in self join query.
select
from t1 a, t2 b
where a.id=b.id
not (a.f_col #> b.t_col)

dynamically choose fields from different table based on existense

I have two tables A and B.
Both the tables have same number of columns.
Table A always contains all ids of Table B.
Need to fetch row from Table B first if it does not exist then have
to fetch from Table A.
I was trying to dynamically do this
select
CASE
WHEN b.id is null THEN
a.*
ELSE
b.*
END
from A a
left join B b on b.id = a.id
I think this syntax is not correct.
Can some one suggest how to proceed.
It looks like you want to select all columns from table A except when a matching ID exists in table B. In that case you want to select all columns from table B.
That can be done with this query as long as the number and types of columns in both tables are compatible:
select * from a where not exists (select 1 from b where b.id = a.id)
union all
select * from b
If the number, types, or order of columns differs you will need to explicitly specify the columns to return in each sub query.

Using Count Function and Percentage of Count Total in One Select Statement

I have three data tables Employees, Departments, and Locations.
I want to show the total number of employees in each state and what percentage of the employees are located in that each state. The Employees table and the Departments table have one identical column called Department_ID, and the Departments table and the Locations table have one identical column called Location_ID. Here's what I wrote for my code:
select l.state_province e.count(*) as "Employees in State",
e.count(*)*100/sum(e.count(*)) over ()
from employees e
full outer join departments d on e.department_id = d.department_id
full outer join locations l on l.location_id = d.location_id
order by l.state_province;
However, the error "from keyword not found where expected" shows up when I run the code. How do I fix it?
You need group by. And regular joins should be fine:
select l.state_province, count(*) as "Employees in State",
count(*) * 100/sum(count(*)) over ()
from employees e join
departments d
on e.department_id = d.department_id join
locations l
on l.location_id = d.location_id
group by l.state_province
order by l.state_province;

Full outer join on multiple tables in PostgreSQL

In PostgreSQL, I have N tables, each consisting of two columns: id and value. Within each table, id is a unique identifier and value is numeric.
I would like to join all the tables using id and, for each id, create a sum of values of all the tables where the id is present (meaning the id may be present only in subset of tables).
I was trying the following query:
SELECT COALESCE(a.id, b.id, c.id) AS id,
COALESCE(a.value,0) + COALESCE(b.value,0) + COALESCE(c.value.0) AS value
FROM
a
FULL OUTER JOIN
b
ON (a.id=b.id)
FULL OUTER JOIN
c
ON (b.id=c.id)
But it doesn't work for cases when the id is present in a and c, but not in b.
I suppose I would have to do some bracketing like:
SELECT COALESCE(x.id, c.id) AS id, x.value+c.value AS value
FROM
(SELECT COALESCE(a.id, b.id), a.value+b.value AS value
FROM
a
FULL OUTER JOIN
b
ON (a.id=b.id)
) AS x
FULL OUTER JOIN
c
ON (x.id = c.id)
It was only 3 tables and the code is ugly enough already imho. Is there some elegant, systematic ways how to do the join for N tables? Not to get lost in my code?
I would also like to point out that I did some simplifications in my example. Tables a, b, c, ..., are actually results of quite complex queries over several materialized views. But the syntactical problem remains the same.
I understood you need to sum the values from N tables and group them by id, correct?
For that I would do this:
Select x.id, sum (x.value) from (
Select * from a
Union all
Select * from b
Union all........
) as x group by x.id;
Since the n tables are composed by the same fields you can union them all creating a big table full of all the id - value tuples from all tables. Use union all because union filters for duplicates!
Then just sum all the values grouped by id.

TSQL - How do I use SUM in a virtual COLUMN inside a select?

create proc sp_SumVirtual
as
select a.year, sum(b.PriceDay*b.AmmountDays) profit
from vehicles a, rent b
where a.Matriculation = b.Matriculation
GROUP BY a.year
Okay so, with this I got the amount of money EACH car has made, but I need the whole amount. So, is there a way I can make SUM from the virtual table Profit? Because that is all I need..or do you suggest another way?
Use the WITH ROLLUP on your GROUP BY clause:
SELECT
a.year, SUM(b.PriceDay*b.AmmountDays) profit
FROM
dbo.vehicles a
INNER JOIN
dbo.rent b ON a.Matriculation = b.Matriculation
GROUP BY
a.year WITH ROLLUP
This will give you an additional row with NULL as the value of year and the value in the sum column will be the total sum over all grouped rows.
Update: so you want to have the sum for each year, but also another column with the total sum over all rows of all years??
Try this:
SELECT
a.year,
SUM(b.PriceDay*b.AmmountDays) profit,
(SELECT SUM(b2.PriceDay * b2.AmountDays)
FROM dbo.vehicles a2
INNER JOIN dbo.rent b2 ON a2.Matriculation = b2.Matriculation) AS TotalProfit
FROM
dbo.vehicles a
INNER JOIN
dbo.rent b ON a.Matriculation = b.Matriculation
GROUP BY
a.year
HOWEVER: this will NOT be performing very well, since you calculate the TotalProfit again and again - for each row that will be output.....
Select v.year, Sum(r.PriceDay*r.AmmountDays) profit
From vehicles v Join rent r
On r.Matriculation = v.Matriculation
Group By v.year
With RollUp
You could use a temp table along with UNION ALL:
SELECT
a.year, SUM(b.PriceDay*b.AmmountDays) profit
INTO #Temp
FROM
dbo.vehicles a
INNER JOIN
dbo.rent b ON a.Matriculation = b.Matriculation
GROUP BY
a.year
SELECT *
FROM #Temp
UNION ALL
SELECT year, Sum(profit)
FROM #Temp
Group by year