Get the difference between two values - postgresql

I got totally stuck on comparing two tables and getting the difference between them
So here we go:
I got table a with the following columns
Name|Value|Date
and the second table b with the same columns
What i wanna do now is get the difference between the values like
Table a
Name|Value|Date
Test|3|2013-20-06
Table b
Name|Value|Date
Test|9|2013-20-06
What i wann get is the difference between the 3 and 9 so i would recieve 6
Any Idea how i'm able to get that from a query in my PostgreSQL-DB?

Join the tables and select the difference:
select a.name, b.value - a.value, a.date
from a inner join b on a.name = b.name and a.date = b.date

Related

How to get unique rows by one column but sort by the second

There is an example request in which there are several joins.
SELECT DISTINCT ON(a.id_1) 1, a.name, b.task, c.created_at
FROM a
INNER JOIN b ON a.id_2 = b.id
INNER JOIN c ON a.ID_2 = c.id
WHERE a.deleted_at IS NULL
ORDER BY a.id_1 desc
In this case, the query will work, sorting by unique values ​​of id_1 will take place. But I need to sort by the column a.name. In this case, postresql will swear with the words ERROR: SELECT DISTINCT ON expressions must match initial ORDER BY expressions.
The following query can serve as a solution to the problem:
SELECT *
FROM(
SELECT DISTINCT ON(a.id_1) a.name, b.task, c.created_at
FROM a
INNER JOIN b ON a.id_2 = b.id
INNER JOIN c ON a.ID_2 = c.id
WHERE a.deleted_at IS NULL
)
ORDER_BY a.name desc
But in reality the database is very large and such a query is not optimal. Are there other ways to sort by the selected column while keeping one uniqueness?

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.

T-SQL select all IDs that have value A and B

I'm trying to find all IDs in TableA that are mentioned by a set of records in TableB and that set if defined in Table C. I've come so far to the point where a set of INNER JOIN provide me with the following result:
TableA.ID | TableB.Code
-----------------------
1 | A
1 | B
2 | A
3 | B
I want to select only the ID where in this case there is an entry for both A and B, but where the values A and B are based on another Query.
I figured this should be possible with a GROUP BY TableA.ID and HAVING = ALL(Subquery on table C).
But that is returning no values.
Since you did not post your original query, I will assume it is inside a CTE. Assuming this, the query you want is something along these lines:
SELECT ID
FROM cte
WHERE Code IN ('A', 'B')
GROUP BY ID
HAVING COUNT(DISTINCT Code) = 2;
It's an extremely poor question, but you you probably need to compare distinct counts against table C
SELECT a.ID
FROM TableA a
GROUP BY a.ID
HAVING COUNT(DISTINCT a.Code) = (SELECT COUNT(*) FROM TableC)
We're guessing though.

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.

SQL - Distinct entries with some cruddy data

I have an issue. I have 2 tables that are linked by an ID.
TableA
ID
Price
Other_Stuff
TableB
ID
TableA_ID
Type
Age
I can do a:
SELECT
M1.Age,
F1.Age,
M2.Age,
F2.Age,
FROM TableA
LEFT JOIN (SELECT * FROM TableB WHERE TableB.Type='1') AS M1 ON M1.TableA_ID=TableA.ID
LEFT JOIN (SELECT * FROM TableB WHERE TableB.Type='2') AS F1 ON F1.TableA_ID=TableA.ID
LEFT JOIN (SELECT * FROM TableB WHERE TableB.Type='3') AS M2 ON M2.TableA_ID=TableA.ID
LEFT JOIN (SELECT * FROM TableB WHERE TableB.Type='4') AS F2 ON F2.TableA_ID=TableA.ID
And things work as expected while the data is good, but the data is not always good. Normally there is at most one or none of each Type in TableB. The problem is that for older data in the table, before types 3 and 5 existed, there is the possibility that there are two type 1 and or two type 2s. in that case I would want the second type 1 to be treated as a type 2 and the second type 2 is treated as a type 4.
Basically I want a single record returned for each entry in TableA with the 4 ages listed in their own columns, I do not want multiple records for each in TableA.
I am using MS SQL 2000.... old, i know.
Thanks,
try changing the subqueries to something like:
SELECT TOP 1 * FROM TableB WHERE TableB.Type='1 AND TableA_ID=TableA.ID