Joining one table twice in postgresql - postgresql

I have two columns in the same table that I want to join in Postgresql but for some reason I’m getting this error. Don’t know how to figure it out. Please help.
[42P01] ERROR: relation "a" does not exist
Position: 10
X table contains two pools(ABC,XYZ), ids, numbers and description. If an ID exists in one pool but not in the other, it should update description column to “ADD”. Pools need to be joined on number.
UPDATE A
SET A.Description = 'ADD'
FROM X AS A
LEFT JOIN X AS B ON B.number = A.number
AND B.id = 'ABC'
WHERE A.id = 'XYZ'
AND B.number IS NULL
AND A.Description IS NULL;

With standard SQL you can't do a join as part of an update, but what you can do is include a subquery to select the id's to update. The subquery can contain a join. I'm not entirely clear on what you're actually trying to accomplish, but you could do something like this:
UPDATE x SET description='ADD' WHERE number IN (
SELECT a.number FROM x AS a
LEFT OUTER JOIN x AS b ON a.number=b.number AND a.id='XYZ' AND b.id='ABC'
WHERE b.number IS NULL
);
This will join the table x with itself and will select (and update) any numbers's that don't have a matching number in the 'ABC' and 'XYZ' zone.
PostgreSQL does have a UPDATE FROM syntax that does let you update with complex subqueries. It's more flexible but it's non-standard. You can find an example of this type of query here.

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;

PostGres joins Using JSONB

I have two tables which look like such
Organizations
Id (primary_key. big int)
Name (text)
CustomInformations
Id (primary_key. big int)
ConnectedIdentifiers (JSONB)
Info (text)
CustomInformations's ConnectedIdentifiers column contains a JSONB structure which looks like
{ 'organizations': [1,2,3] }
This means that there's an array of organizations with those ids 1, 2, 3, which are related to that particular CustomInformation
I'm trying to do a JOIN where given a CustomInformation Id will also get me all the Organizations names
I tried this after looking at some examples:
SELECT * FROM CustomInformations ci
INNER JOIN Organizations o on jsonb_array_elements(ci.ConnectedIdentifiers->'19') = o.id
WHERE
ci.id = 5
I got an error No operator matches the given name and argument type(s). You might need to add explicit type casts.
Is this the right approach? And if so what is wrong with my syntax?
Thanks
You cannot use jsonb_array_elements() in this way because the function returns set of rows. It should be placed in a lateral join instead. Use jsonb_array_elements_text() to get array elements as text and cast these elements to bigint:
select ci.*, o.*
from custominfo ci
-- lateral join
cross join jsonb_array_elements_text(ci.connectedidentifiers->'organizations') ar(elem)
join organizations o
on elem::bigint = o.id
where ci.id = 5

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.

How to use GROUP BY with Firebird?

I'm trying create a SELECT with GROUP BY in Firebird but I can't have any success. How could I do this ?
Exception
Can't format message 13:896 -- message file C:\firebird.msg not found.
Dynamic SQL Error.
SQL error code = -104.
Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause).
(49,765 sec)
trying
SELECT FA_DATA, FA_CODALUNO, FA_MATERIA, FA_TURMA, FA_QTDFALTA,
ALU_CODIGO, ALU_NOME,
M_CODIGO, M_DESCRICAO,
FT_CODIGO, FT_ANOLETIVO, FT_TURMA
FROM FALTAS Falta
INNER JOIN ALUNOS Aluno ON (Falta.FA_CODALUNO = Aluno.ALU_CODIGO)
INNER JOIN MATERIAS Materia ON (Falta.FA_MATERIA = Materia.M_CODIGO)
INNER JOIN FORMACAOTURMAS Turma ON (Falta.FA_TURMA = Turma.FT_CODIGO)
WHERE (Falta.FA_CODALUNO = 238) AND (Turma.FT_ANOLETIVO = 2015)
GROUP BY Materia.M_CODIGO
Simple use of group by in firebird,group by all columns
select * from T1 t
where t.id in
(SELECT t.id FROM T1 t
INNER JOIN T2 j ON j.id = t.jid
WHERE t.id = 1
GROUP BY t.id)
Using GROUP BY doesn't make sense in your example code. It is only useful when using aggregate functions (+ some other minor uses). In any case, Firebird requires you to specify all columns from the SELECT column list except those with aggregate functions in the GROUP BY clause.
Note that this is more restrictive than the SQL standard, which allows you to leave out functionally dependent columns (ie if you specify a primary key or unique key, you don't need to specify the other columns of that table).
You don't specify why you want to group (because it doesn't make much sense to do it with this query). Maybe instead you want to ORDER BY, or you want the first row for each M_CODIGO.

Postgres - Get data from each alias

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 [...]