Postgres - Get data from each alias - postgresql

In my application i have a query that do multiple joins with a table position. Just like this:
SELECT *
FROM (...) as trips
join trip as t on trips.trip_id = t.trip_id
left outer join vehicle as v on v.vehicle_id = t.trip_vehicle_id
left outer join position as start on trips.start_position_id = start.position_id and start.position_vehicle_id = v.vehicle_id
left outer join position as "end" on trips.end_position_id = "end".position_id and "end".position_vehicle_id = v.vehicle_id
left outer join position as last on trips.last_position_id = last.position_id and last.position_vehicle_id = v.vehicle_id;
My table position has 35 columns(for example position_id).
When I run the query, in result should appear the table position 3 times, start, end and last. But postgres can not distinguish between, for exemplar, start.position_id, end.position_id and last.position_id. So this 3 columns are group and appear as one, position_id.
As the data from start.position_id and end.position_id are different, the column, position_id, that appear in result, it's empty.
Without having to rename all the columns, like this: start.position_id as start_position_id.
How can i get each group of data separately, for exemple, get all columns from the table 'start'. In MYSQL i can do this operation by calling fetch_fields, and give the function an alias, like 'start'.
But i can i do this in Postgres?
Best Regards,
Nuno Oliveira

My understanding is that you can't (or find it difficult to) discern between which table each column with a shared name (such as "position_id") belongs to, but only need to see one of the sets of shared columns at any one time. If that is the case, use tablename.* in your SELECT, so SELECT trips.*, start.*... would show the columns from trips and start, but no columns from other tables involved in the join.
SELECT [...,] start.* [,...] FROM [...] atable AS start [...]

Related

Return closest timestamp from Table B based on timestamp from Table A with matching Product IDs

Goal: Create a query to pull the closest cycle count event (Table C) for a product ID based on the inventory adjustments results sourced from another table (Table A).
All records from Table A will be used, but is not guaranteed to have a match in Table C.
The ID column will be present in both tables, but is not unique in either, so that pair of IDs and Timestamps together are needed for each table.
Current simplified SQL
SELECT
A.WHENOCCURRED,
A.LPID,
A.ITEM,
A.ADJQTY,
C.WHENOCCURRED,
C.LPID,
C.LOCATION,
C.ITEM,
C.QUANTITY,
C.ENTQUANTITY
FROM
A
LEFT JOIN
C
ON A.LPID = C.LPID
WHERE
A.facility = 'FACID'
AND A.WHENOCCURRED > '23-DEC-22'
AND A.ADJREASONABBREV = 'CYCLE COUNTS'
ORDER BY A.WHENOCCURRED DESC
;
This is currently pulling the first hit on C.WHENOCCURRED on the LPID matches. Want to see if there is a simpler JOIN solution before going in a direction that creates 2 temp tables based on WHENOCCURRED.
I have a functioning INDEX(MATCH(MIN()) solution in Excel but that requires exporting a couple system reports first and is extremely slow with X,XXX row tables.
If you are using Oracle 12 or later, you can use a LATERAL join and FETCH FIRST ROW ONLY:
SELECT A.WHENOCCURRED,
A.LPID,
A.ITEM,
A.ADJQTY,
C.WHENOCCURRED,
C.LPID,
C.LOCATION,
C.ITEM,
C.QUANTITY,
C.ENTQUANTITY
FROM A
LEFT OUTER JOIN LATERAL (
SELECT *
FROM C
WHERE A.LPID = C.LPID
AND A.whenoccurred <= c.whenoccurred
ORDER BY c.whenoccurred
FETCH FIRST ROW ONLY
) C
ON (1 = 1) -- The join condition is inside the lateral join
WHERE A.facility = 'FACID'
AND A.WHENOCCURRED > DATE '2022-12-23'
AND A.ADJREASONABBREV = 'CYCLE COUNTS'
ORDER BY A.WHENOCCURRED DESC;

Postgresql: can I join colums with the same name in a materialized view?

I use this query to join two tables:
SELECT *
FROM horses h
RIGHT JOIN races r ON h.racedate = r.racedate
AND h.racename = r.racename
AND h.racetime = r.racetime
ORDER BY r.racedate, r.racetime
This works without a problem, but if I try:
CREATE MATERIALIZED VIEW allracesview AS
SELECT *
FROM horses h
RIGHT JOIN races r ON h.racedate = r.racedate
AND h.racename = r.racename
AND h.racetime = r.racetime
ORDER BY r.racedate, r.racetime DESC
I get the error
ERROR: FEHLER: Spalte »racetime« mehrmals angegeben
Which means "Column racetime is specified multiple times" and only 3 columns are added to the view.
How can I join these two tables in a materialized view?
Like #a_horse_with_no_name said in the comments, select * does return all columns of all tables. As you have the same columns in both tables, you have duplicated column names in the result.
How can I join these two tables in a materialized view? Without an explicit column list?
You can use a USING clause for the JOIN condition. The output of JOIN USING` suppresses redundant columns, so go with
CREATE MATERIALIZED VIEW allracesview AS
SELECT *
FROM horses
RIGHT JOIN races USING (racedate, racename, racetime)
ORDER BY racedate, racetime DESC

Issue using INNER JOIN on multiple tables in Postgres

I am trying to create a new table by using inner join to combine multiple tables. All, the tables have a primary key/column called reach_id. I have a primary table called q3_studies. I want all of the columns from this table. I then have multiple other tables that have reach_id + another column. I want to JOIN this table ON reach_id that matches q3_studies but only include the other columns (so I don't have redundant reach_id columns). My first attempt seems to work if I run it from SELECT * ... using a LIMIT 1000; at the end, but adds redundant reach_ids.
SELECT * FROM second_schema.q3_studies s
INNER JOIN second_schema.bs_trigger_q3 b ON s.reach_id = b.reach_id
INNER JOIN second_schema.mod_unmod_q3 m ON s.reach_id = m.reach_id LIMIT 1000;
How can I amend this to add only the additional columns (ex: bs_trigger_q3 has an additional columns called bs_trigger, mod_unmod_q3 has an additional column called mod_unmod)?
Secondly, if I try to create a new table, I get an error: column reach_id specified more than one. What am I doing wrong here?
CREATE TABLE first_schema.report_q3 AS
SELECT * FROM second_schema.q3_studies s
INNER JOIN second_schema.bs_trigger_q3 b ON s.reach_id = b.reach_id
INNER JOIN second_schema.mod_unmod_q3 m ON s.reach_id = m.reach_id;
Instead of select * you need to list the columns you want explicitly. This is good practice in any case. It also allows you to rename columns e.g. s.column_A as "foo_column"
In the future the schema may change.
CREATE TABLE first_schema.report_q3 AS
SELECT
s.reach_id,
s.column_A, s.column_B,
b.column_C, b.column_D,
m.column_E, m.column_F
FROM second_schema.q2_studies s
INNER JOIN second_schema.bs_trigger_q3 b ON s.reach_id = b.reach_id
INNER JOIN second_schema.mod_unmod_q3 m ON s.reach_id = m.reach_id
;
If your editor does not help you with column names consider a different editor.

postgresql lef join doesn't works

I would like to add to the table A all the column of the table B, doing a join based on a common column (type numeric). I am trying to do it using the LEFT JOIN but the columns added are all blank. this is impossible because table b stores, among others, the same ID values . Where I am wrong?
Select * from "2017_01" left join "Registry_2017" on '2017_01.ID' = 'Registry_2017.ID';
You are doing wrong.. I don't know why you can use right for Table calling "2017_01" and different with this '2017_01.ID'..
' = Single quote identifies as String
" = Double quote identifies as Table or Column to escape Naming
Select
*
From
"2017_01"
left join "Registry_2017" on '2017_01.ID' = 'Registry_2017.ID';
So when you doing this '2017_01.ID' = 'Registry_2017.ID' The condition will always become false because those 2 different String are not equal. Postgresql look the condition not as Table and Column but String because you are using Single quote
Select
*
from
"2017_01"
left join "Registry_2017" on "2017_01"."ID" = "Registry_2017"."ID";
So the query should be like that.. Even you already got answer and it got work i must tell this..

Postgres join table: Return only records from one table but with values from others [duplicate]

This question already has answers here:
Nested Case statement type error (postgres)
(2 answers)
Closed 7 years ago.
I have a table with ~5,000 records. I have made three join columns in this table. The values in each column are not unique. I want to join to another table (sequentially) by each of these three columns to return values given a condition.
The join table contains multiple columns. Three of these columns are the join columns which will correspond to the first tables' join columns. The join columns in the join table are unique. I want to take the values from the join table and bring to a new column in the first table.
I have a code that I have put together from other suggestions and it runs but I am receiving over 8 million records in the return table. I want the table to only have the records from the first table.
Here is the code:
CREATE TABLE current_condition_joined AS SELECT
a.id, a.geom, a.condition_join_1, a.condition_join_2, a.condition_join_3,
coalesce(b.condition, c.condition2, d.condition3) as current_condition,
coalesce(b.ecosite, c.ecosite2, d.ecosite3) as current_ecosite,
coalesce(b.ecophase, c.ecophase2, d.ecophase3) as current_ecophase,
coalesce(b.consite, c.consite2, d.consite3) as current_consite,
coalesce(b.conphase, c.conphase2, d.conphase3) as current_conphase
FROM current_condition a
LEFT JOIN boreal_mixedwood_labeled b ON a.condition_join_1 = b.label
LEFT JOIN boreal_mixedwood_labeled c ON a.condition_join_2 = c.label2
LEFT JOIN boreal_mixedwood_labeled d ON a.condition_join_3 = d.label3
WHERE b.condition != 'ERROR' and c.condition2 != 'ERROR';
I want to get the values from the first join if condition is not ERROR, else the values from the second join if condition is not ERROR, else the values of the third join.
I've looked around, but all examples are asking slightly different things then I am so I can't piece it together.
This is not the same question as: Nested Case statement type error (postgres)
The question asked there was in regard to making a nested statement work. This question is about how the join works. Two different questions, two different posts.
Try add a DISTINCT.
CREATE TABLE current_condition_joined AS SELECT DISTINCT
a.id, a.geom, a.condition_join_1, a.condition_join_2, a.condition_join_3,
coalesce(b.condition, c.condition2, d.condition3) as current_condition,
coalesce(b.ecosite, c.ecosite2, d.ecosite3) as current_ecosite,
coalesce(b.ecophase, c.ecophase2, d.ecophase3) as current_ecophase,
coalesce(b.consite, c.consite2, d.consite3) as current_consite,
coalesce(b.conphase, c.conphase2, d.conphase3) as current_conphase
FROM current_condition a
LEFT JOIN boreal_mixedwood_labeled b ON a.condition_join_1 = b.label
LEFT JOIN boreal_mixedwood_labeled c ON a.condition_join_2 = c.label2
LEFT JOIN boreal_mixedwood_labeled d ON a.condition_join_3 = d.label3
WHERE b.condition != 'ERROR' and c.condition2 != 'ERROR';
You can try use GROUP BY too.
The code you present is what I gave you for your previous question:
Nested Case statement type error (postgres).
But you broke it by moving the conditions b.condition != 'ERROR' and c.condition2 != 'ERROR' to the WHERE clause, which is simply wrong. Consider:
Query with LEFT JOIN not returning rows for count of 0
If rows are multiplied, then your join conditions most probably identify multiple matching rows, multiplying each other. Hard to diagnose while you still refuse to provide the table definition of boreal_mixedwood_labeled like I requested repeatedly for your previous question.