SQL multiple join from one row with string - sql

i have two table like this:
table1
id(int) | desc(TEXT)
--------------------
0 | "desc1"
1 | "desc2"
table2
id(int) | table1_id(TEXT)
------------------------
0 | "0"
1 | "0;1"
i want to select data into table2 and replace table1_id by the desc field in table1, when i have string with ';' separator it means i have multiple selections.
im able to do it for single selection like this
SELECT table1.desc
FROM table2 LEFT JOIN table1 ON table1.id = CAST(table2.table1_id as integer);
Output wanted with a SELECT on table2 where id = 1:
"desc"
------
"desc1, desc2"
Im using Postgresql10, python3.5 and sqlalchemy
I know how to do it by extracting data and processing it with python then query again but im looking for a way to do it with one SQL query.
PS: I cant modify the table2.

You can convert the CSV value into an array, then join on that:
select string_agg(t1.descr, ',') as descr
from table2 t2
join table1 t1 on t1.id = any (string_to_array(t2.table1_id, ';')::int[])
where t2.id = 1

That is really an abominable data design.
Consequently you will have to write a complicated query to get your desired result:
SELECT string_agg(table1."desc", ', ')
FROM table2
CROSS JOIN LATERAL regexp_split_to_table(table2.table1_id, ';') x(d)
JOIN table1 ON x.d::integer = table1.id
WHERE table2.id = 1;
string_agg
--------------
desc1, desc2
(1 row)

Related

Returning filtered results from sql select

For context this is a search that can be called by and end user, they will provide the comma delimited string containing the Table 3 ID's to be searched and Table 2 text value to search for.
I want to perform a select query that will only return matching results from the CTE where all values in the fieldValuePairTable match. Currently it returns any matches.
DECLARE #fieldvaluepairtable TABLE (Table3Id int, value varchar(max));
INSERT INTO #fieldvaluepairtable SELECT * FROM dbo.split_string_XML('123:york,456:halifax',',');
with cte as (
select Table1.id, Table3.id as t3id, Table2.text
from Table1
inner join Table2 on Table1.id = Table2.Table1Id
inner join Table3 on Table2.id = Table3.Table2Id)
select distinct id
from cte
join #fieldvaluepairtable DataTable on (text like cast( '%' + DataTable.value + '%' as varchar ) and t3id = DataTable.Table3Id)
For example;
A possible result set for the CTE looks like:
id t3id text
---- ----- ---------------
100 123 york
100 456 halifax
200 123 york
200 456 manchester
The select statement would then return
id
----
100
200
I want to select ID's where ALL values in fieldvaluepairtable match rather than when ANY match.
Meaning I want to see the following results
id
----
100
The code will be used in a stored procedure so it needs to be able to handle any number of key value pairs being passed into the fieldvaluepairtable
If I follow you correctly, you can use some relational division technique:
select t1.id
from table1 t1
inner join table2 t2
on t1.id = t2.table1id
inner join table3 t3
on t2.id = t3.table2id
inner join #fieldvaluepairtable x
on t3.text like cast( '%' + x.value + '%' as varchar )
and t3.t3id = x.table3id
group by t1.id
having count(*) = (select count(*) from #fieldvaluepairtable)
Basically this searches for matches, then groups the result by t1.id, and ensures that the number of rows in the group is equal to the count of search criteria.

How to retrieve the data of second table (Table 2) by pointing data of another table (Table 1)

Can someone suggest/help on the below SQL query.
I have two table(Called Table 1 and Table 2), In Table 1 i have the value 11111 in ORG column, using this value i have to identify the correspondence value 1234(Which under MIDA).
MIDA have same value in both table, using this 1234(Which under MIDA, Table 1), i have to retrieve all data from Table 2 where MIDA=1234.
Query should be From Table 1 using ORG value identify the MIDA value and using MIDA value retrieve all data from Table 2 where there are same MIDA(bath Table 1 and Table 2) value.
Table:-1
PK OFFIC MIDA DEPT VER ORG
____________________________________________
123 321 1234 AA1 1.0 11111
Table:-2
FLOW FREE MIDA PRINT TIME ID
____________________________________________________
XYZ A1 1234 test 2019-06-11 1.0
An INNER JOIN answers your question;
SELECT Table2.*
FROM Table2
INNER JOIN Table1
ON Table1.MIDA = Table2.MIDA
WHERE Table1.ORG = '11111'
It sounds like you just need a simple join query:
SELECT t2.*
FROM Table2 t2
INNER JOIN Table1 t2
ON t2.MIDA = t2.MIDA
WHERE
t1.ORG = '11111';
Didn't test:
SELECT * FROM Table2
WHERE MIDA IN (
SELECT MIDA FROM Table1
WHERE ORG = "YOUR ORG VALUE")
EDIT1 Format
You may use JOIN for your requirement. You may find this link for more info JOIN.
For your above query:-
SELECT T2.FLOW, T2.FREE, T2.MIDA, T2.PRINT, T2.TIME, T2.ID
FROM Table2 AS T2
INNER JOIN TABLE1 AS T1 ON T1.MIDA=T2.MIDA
WHERE T1.ORG = 1111 ------ this is optional for fetching only record of org '1111'
SELECT * from TABLE1 t1
INNER JOIN TABLE2 t2
ON t1.MIDA=t2.MIDA
WHERE t1.ORG=1111
given ORG is an int value else it would be '1111'

SQL: checking if row contains contents of another cell

I'm having difficulty with a SQL query.
I have two tables:
Table 1
ID/First Name
1 Ben
2 Barry
3 Birl
Table 2
ID/Full name
1 Ben Rurth
2 Barry Bird
3 Burney Saf
I want to run a check between the two tables where if the contents of the First Name in Table 1 is not in the Full name in table 2 the result will be returned, e.g. returning id 3, Birl, in the above example.
I have been trying queries like:
SELECT First_Name
from Table_1
WHERE NOT EXIST (SELECT Full_name from Table_2)
with no luck so far.
You can make use of LIKE clause combined with concatenation.
SELECT t1.First_Name,t2.Full_Name
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.Full_Name NOT LIKE '%' || t1.First_Name || '%'
Or
SELECT t1.First_Name,t2.Full_Name
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.Full_Name NOT LIKE CONCAT('%', t1.First_Name, '%')
This is, understanding that both tables shares the ID column.

SQL Select Query - "Pairing" Records Together

Here's my data:
Table1...
id
field1
field2
...
Table2...
id
table1_original_id
table1_new_id
Table1 holds records that cannot themselves be updated though I built a mechanism for my users to be able to "update" them... they select a record, make changes, and those changes are actually submitted as a new record. For conversation's sake let's assume there are currently 10 records in Table1 with IDs 1 through 10. User submits an update to ID 3. ID 3 remains as it was and a new record, ID 11, is added to Table1. Along with this new record, Table2 gets a new record, with ID = 1, t1_original_id = 3 and t1_new_id = 11.
What would be by SQL select to retrieve the "pairs" of records from Table1... in this case the query would provide me with... IDs 3 and 11.
scratching head
I don't think it matters much by DB platform is Postgres 8.4 and I'm retrieving the data via PHP to be processed in jqGrid. Bonus points if you can point me in the direction of displaying each pair of records in a separate jqGrid!
Thanks for your time and effort.
=== EDIT ===
The following is a sample of what I need returned from the query based on the scenario above:
id field1 field2
3 blah stuff
11 more things
Once I have these pairs back I can process them further, as necessary, on the PHP side.
Standard SQL solution
To get two separate rows (as later specified in the Q update) use a UNION query:
SELECT 'old' AS version, t1.id, t1.field1, t1.field2
FROM table1 t1
JOIN table2 t2 ON t2.table1_original_id = t1.id
WHERE t2.id = $some_t2_id -- your t2.id here!
UNION ALL
SELECT 'new' as version, t1.id, t1.field1, t1.field2
FROM table1 t1
JOIN table2 t2 ON t2.table1_new_id = t1.id
WHERE t2.id = $some_t2_id; -- your t2.id here!
Note: this is one query.
Returns as requested, plus a column version to distinguish the rows reliably:
version | id | field1 | field2
--------+----+--------+--------
old | 3 | blah | stuff
new | 11 | more | things
Faster Postgres-specific solution
A more sophisticated, but shorter and faster solution:
SELECT version, id, field1, field2
FROM (
SELECT unnest(ARRAY['old', 'new']) AS version
,unnest(ARRAY[table1_original_id, table1_new_id]) AS id
FROM table2 t2 WHERE t2.id = $some_t2_id -- your t2.id here!
) t2
JOIN table1 USING (id);
Same result.
-> SQLfiddle demo for both.
You'll need to JOIN to Table1 twice, something like:
SELECT orig.id AS Orig_ID
, orig.value AS Orig_Value
, n.id AS New_ID
, n.value AS New_Value
FROM Table2 a
JOIN Table1 AS orig
ON a.table1_original_id = orig.id
JOIN Table1 AS n
ON a.table1_new_id = n.id
Demo: SQL Fiddle
Update:
To get them paired as you want without manually choosing a set you'll need something like this:
SELECT sub.id,sub.value
FROM (SELECT a.id as Update_ID,o.id,o.value, '1' AS sort
FROM Table2 a
JOIN Table1 AS o
ON a.table1_original_id = o.id
UNION
SELECT a.id as Update_ID, n.id,n.value, '2' AS sort
FROM Table2 a
JOIN Table1 AS n
ON a.table1_new_id = n.id
) AS sub
ORDER BY Update_ID,sort
Demo: Sql Fiddle
Notes: Change UNION to UNION + ALL, can't post those words next to each other due to firewall limitation.
The hard-coded '1' and '2' are so that original always appear before new.

sql join int varchar

I've been searching the questions but havenĀ“t found an answer. I would like to do an inner join with Table 1 and Table 2 , but one field is INT and other is VARCHAR (with the structure "A-INT"). Something like:
Table1 Table2
ID NAME WHATEVER ID USER
1 A-001 --- 1 001
2 A-002 --- 2 002
3 A-003 --- 3 003
3 A-004 --- 4 004
...
How can I construct the query? Something like:
... Table1 INNER JOIN Table2 ON Table1.NAME = Table2.[A-USER] ...
You would need to convert the int value to varchar and concatentate it with 'A-', or get the numeric part of the varchar value and convert to int.
This is done a bit differently depending on what database you are using, for SQL Server it would look like this:
select t1.ID, t1.WHATEVER, t2.USER
from Table1 t1
inner join Table2 t2 on t2.ID = cast(substring(t1.NAME, 3, 3) as int)
Try by concatenation,
SELECT *
FROM Table1 a, Table2 b
WHERE a.Name = 'A-' + b.User
but take note, this decreases the performance.
You want to do inner join on Table1.NAME = Table2.[A-USER].
If Table1.NAME, Table2.[A-USER] column datatype is different means, its not possible to use inner join.