Spring data jpa: join on column with a prefix in the data - spring-data-jpa

I have 2 tables that I want to join, but the value to join on isn't the same in both tables. Is there a way to do this with annotations instead of writing the JPQL or SQL myself? I've looked at the properties in #JoinColumn but none of them seem related to my problem.
I want to join on table_one.fk = 'prefix_' || table_two.fk
Table one:
id fk
--------
1 fk1
2 fk2
3 fk3
4 fk4
Table two:
id fk
--------------------
uuid1 prefix_fk1
uuid2 prefix_fk2
uuid3 prefix_fk3
uuid4 prefix_fk4

Related

show records that have only one matchin row in another table

I need to write a sql code that probably is very simple but I am very new to it.
I need to find all the records from one table that have matching id (but no more than one) from the other table. eg. one table contains records of the employees and the second one with employees' telephone numbers. i need to find all employees with only one telephone no
Sample data would be nice. In absence of:
SELECT
employees.employee_id
FROM
employees
LEFT JOIN
(SELECT distinct on(employee_id) employee_id FROM emp_phone) AS phone
ON
employees.employee_id = phone.employee_id
WHERE
phone.employee_id IS NOT NULL;
You need a join of the 2 tables, group by employee and the condition in the having clause:
SELECT e.employee_id, e.name
FROM employees e INNER JOIN numbers n
ON e.employee_id = n.employee_id
GROUP BY e.employee_id, e.name
HAVING COUNT(*) = 1;
If there can be more than a few numbers per employee in the table with the employees' telephone numbers (calling it tel), then it's cheaper to avoid GROUP BY and HAVING which has to process all rows. Find employees with "unique" numbers using a self-anti-join with NOT EXISTS.
While you don't need more than the employee_id and their unique phone number, you don't even have to involve the employee table at all:
SELECT *
FROM tel t
WHERE NOT EXISTS (
SELECT FROM tel
WHERE employee_id = t.employee_id
AND tel_number <> t.tel_number -- or use PK column
);
If you need additional columns from the employee table:
SELECT * -- or any columns you need
FROM (
SELECT employee_id AS id, tel_number -- or any columns you need
FROM tel t
WHERE NOT EXISTS (
SELECT FROM tel
WHERE employee_id = t.employee_id
AND tel_number <> t.tel_number -- or use PK column
)
) t
JOIN employee e USING (id);
The column alias in the subquery (employee_id AS id) is just for convenience. Then the outer join condition can be USING (id), and the ID column is only included once in the result, even with SELECT * ...
Simpler with a smart naming convention that uses employee_id for the employee ID everywhere. But it's a widespread anti-pattern to use employee.id instead.
Related:
JOIN table if condition is satisfied, else perform no join

Postgres Query to join two tables

I have two tables in Postgres database. In each table there is a column which represent same number. I have tried few join queries to join both tables with similar column numbers but none of them are giving me the expected output.
user_id column from Table 1 is equal to Id column in Table 2
How can join these two tables?
I have tried below and some other queries as well but it didn't get what I wanted
SELECT members.access_level, members.user_id FROM members INNER JOIN users ON members.user_id = users.id;
Tables columns looks like below,
Members table
id |access_level |source_id |user_id |type
Users Table
id |email |name |username
Query output should look as below:
username |name |email |access_level
SELECT u.username
, u.name
, u.email
, m.access_level
FROM users u
JOIN members m ON (u.id = m.user_id)
;
If you want users that are not included in the members table you can join with a LEFT JOIN
To address your question asked in the comments I believe you'd be looking for something like the following:
UPDATE members SET access_level = 'dev' WHERE access_level = '30';
This is assuming that the column is already of type text. Otherwise, you'll need to change the data type first using the following:
ALTER TABLE members
ALTER access_level SET DATA TYPE text;
SELECT users.*, members.user_id, members.acces_level
FROM members
LEFT JOIN users
WHERE users.id = members.user_id

Need an efficient select query

I would like to know an efficient to way to fetch the data in the following case.
There are two tables say Table1 and Table2 having two common field say contry and pincode and other table "Table3" having key fields of first two tables (DNO, MPNO).
Here is the little glitch, In table3 data, if it is having DNO it wont have MPNO
So when in the selection screen(Pic no2) if the use enter any thing, result should be as follows
**MFID | DNO | MPNO | COUNTRY | PINCODE**
----------
00001 | 10011 | novalue | IN | 4444
00002 | Novalue | 1200 | IN | 5555
00003 | 300 | novalue | US | 9999
( as you can observe if DNO present no MPNO , vice versa )
Please have a look at the pictures for a clear picture :-)
Table Relation:
Selection screen with select options:
The code shouldn't be long.
PSEUDO CODE:
Select queries:
Select * from table3 into it_table3.
Select * from table1 FOR ALL ENTRIES IN it_table3 INTO it_table1
WHERE dno = table3-dno.
Select * from table2 FOR ALL ENTRIES IN it_table3 INTO it_table2
WHERE mpno = table3-mpno.
Loop at internal table 3 and build final table.
LOOP at it_table3 into wa_table3.
IF wa_table3-dno IS NOT INITIAL.
READ it_table1 where dno = wa_table3-dno.
ELSE.
READ it_table2 where mpno = wa_table3-mpno.
ENDIF.
ENDLOOP.
Hope this was the answer you were hoping to find!
Building of efficient select will require information about obligatory fields in your selection screen, as well as about alleged production size of all 3 tables. However, without this information let's assume that table1 and table2 are reference tables and table3 is a transaction table, as onr can assume from their structure. It would be sensible to build selection in a following way:
Selecting data from reference tables. As you said fields DNO/MPNO are mutually exclusive then there will be no hits of country/pincode pair in both reference tables, so JOIN is useless here. However we can merge 2 result sets in single itab without any constraints' violations.
TYPES: BEGIN OF tt_result,
dno TYPE table1-dno,
mpno TYPE table2-mpno,
country TYPE table1-country,
pincode TYPE table1-pincode,
...other field from table3
END OF tt_result.
DATA: itab_result TYPE tt_result.
SELECT dno
FROM table1
INTO CORRESPONDING FIELDS OF TABLE itab_result
WHERE pincode IN so_pincode
AND country IN so_country.
SELECT mpno
FROM table2
APPENDING CORRESPONDING FIELDS OF TABLE itab_result
WHERE pincode IN so_pincode
AND country IN so_country.
FOR ALL ENTRIES addition allows specifying the same table in FOR ALL ENTRIES clause and in INTO clause, so we can fill our result table with absent table3 data by DNO/MPNO key.
SELECT *
FROM table3
INTO CORRESPONDING FIELDS OF TABLE itab_result
FOR ALL ENTRIES IN itab_result
ON itab_result~dno = itab3~dno
AND itab_result_mpno = itab3~mpno.

SQL for joining 2 tables but a bit complicated for my understanding

Got a situation thats a bit beyond my understanding.
Table A has the Product, Country and Factory
Table B has the Product, Factory and city.
The scenario is such that sales forecast data flows from the country level via the factory and then to city level. We have factories only in Rotterdam and Amsterdam. The issue is such that the factories in Table A need to be the same as the factory in table B.
I have to clean data for situations C&D where the factories in Table A are wrong and need cleaning. I therefore first need to identify these wrong records:
Here is what I got so far by joining Table A and B
select A.Prod,A.country,A.factory,B.Prod,B.factory,B.City from Table1 A, Table2 B where and A.Prod=B.Prod and A.Factory <>B.Factory
Of course I can find a specific known wrong record by using below SQL, but I need to find for all wrong records without specifying any product or
select A.Prod,A.country,A.factory,B.Prod,B.factory,B.City from Table1 A, Table2 B where A.Prod=B.Prod and A.Factory <>B.Factory
and A.Country ='Norway' and A.Factory ='Rotterdam' and B.City ='Oslo'
Situation 1
Table A
Product Country Factory
ProdA Switzerland Rotterdam
Table B
Product Factory City
ProdA Rotterdam Geneva
Situation 2
Table A
Product Country Factory
Prod Germany Rotterdam
Table B
Product Factory City
ProdB Rotterdam Dresden
Situation 3
Table A
Product Country Factory
ProdC Norway Rotterdam
Table B
Product Factory City
ProdC Amsterdam Oslo
Situation 4
Table A
Product Country Factory
ProdD Finland Rotterdam
Table B
Product Factory City
ProdD Amsterdam Helsinki
From what I understand Your projection for the country in Table A, has to be for a city in table B, which exists in the country in table A.
So, in situation 1, we have
Table A country = Switzerland, Table B city = Geneva.
Since, Geneva is in Switzerland, this is fine
In situation 2, we have
Table A country = Germany, Table B city = Dresden
Since Dresden is in Germany this is fine.
This gives us a clue on how we can attack the problem.
Step 1. Setup a table for your expected country/city
CREATE TABLE COUNTRY_CITY (COUNTRY VARCHAR(60), CITY VARCHAR(60));
STEP 2. Insert the values for expected country/city into table
INSERT INTO COUNTRY_CITY(COUNTRY,CITY) VALUES('GERMANY','DRESDEN');
INSERT INTO COUNTRY_CITY(COUNTRY,CITY) VALUES('SWITZERLAND','GENEVA');
INSERT INTO COUNTRY_CITY(COUNTRY,CITY) VALUES('NORWAY','OSLO');
INSERT INTO COUNTRY_CITY(COUNTRY,CITY) VALUES('FINLAND','HELSINKI');
STEP 3.
select A.Prod,A.country, A.factory, B.Prod, B.factory, B.City,
COUNTRY_CITY.CITY
from
Table1 A
INNER JOIN Table2 B ON A.Prod=B.Prod
INNER JOIN COUNTRY_CITY ON A.COUNTRY = COUNTRY_CITY.COUNTRY
where COUNTRY_CITY.CITY = B.city and A.Factory <> B.Factory
So in step 3, we give the database the knowledge of which city belongs to which country, so that we can do a join from Table A to table B. Once you get that, then the condition on the not matching factories should be the records that you are looking for

Is there a way to have an "automatic" join in postgresql?

I mean the following:
I have 2 parent tables :
table1
id PRIMARY KEY
name TEXT
table2
id PRIMARY KEY
...
and a child table, used fo n-n Relations :
table_child
id PRIMARY KEY
id_1 INT
id_2 INT
where id_1 and id_2 in table_child refer to the column id in table1 and table2.
Now : i often perform request, with a join between table_1 and table_child ON table1.id = table_child.id1, only because i need the value of the column table1.name.
I'm wondering if there is a way to avoid these joins, and declare somehow a "pseudo" column name in table_child, which would not be a real column, but a link to the corresponding column in table_1, so that :
* I can acces the value through table_child.name
* But it is always synchronized with the value table1.name
I hope my explanation was understandable...
Further to my comment above, the answer you're really looking for is something like:
CREATE VIEW
table1_child_view AS
SELECT
table1.name,
table1_child.*
FROM
table1_child
INNER JOIN
table1 ON
table1.id = table1_child.id_1
Then you can run your queries on the new view, such as:
SELECT name FROM table1_child_view WHERE ...