I have two tables TableA and TableB with some data:
IDA|TDATA IDB|TDATA
---+----- ---+-----
1 | A1 1 | B1
2 | A2 2 | B2
and one central table:
ID|TID|TAB|CDATA
--+---+---+-----
10| 1 | A | C1
11| 2 | B | C2
12| 2 | A | C3
Data from central table should be joined with data from TableA or TableB (joining columns TID and TAB). TID is reference to ID in joined table IDA or IDB and column TAB defines which table should be joined. So the final result from query should look like:
ID|TDATA|CDATA
--+-----+-----
10| A1 | C1
11| B2 | C2
13| A2 | C3
How this SQL query should look like?
You can do something like
SELECT c.id,
coalesce( a.tdata, b.tdata ) tdata,
c.cdata
FROM central_table c
LEFT OUTER JOIN tableA a
ON( c.tid = a.ida AND
c.tab = 'A' )
LEFT OUTER JOIN tableB b
ON( c.tid = b.idb AND
c.tab = 'B' )
I would seriously question the data model here, however. If you don't know whether a column in C references a column in A or B, something is generally incorrect in the data model. Fixing the data model will make this (and all your other queries, most likely) much easier to write and much easier to optimize.
If all you want is TAB followed by TID, then the following will work:
SELECT ID, CONCAT(TAB, CAST(TID AS CHAR[2])) AS TDATA, CDATA FROM CentralTable;
If the table names are constant (e.g., nothing other than A or B will be in there), then you can do:
(SELECT ID, TDATA, CDATA FROM CentralTable a
JOIN TableA b ON (a.ID = b.IDA) WHERE a.TAB = 'A')
UNION ALL
(SELECT ID, TDATA, CDATA FROM CentralTable a
JOIN TableB b ON (a.ID = b.IDB) WHERE a.TAB = 'B')
Related
I have two tables TableA and TableB.
The TableA having column called Code Like
'A'
'AB'
'B'
'BB'
In TableB I have column called pnrcode like
'A001'
'AB001'
'B001'
'BC001'
Both tables have no relationship.
I want to join this two table based on TableA code with TableB pnrcode with matching the characters based on TableA
If you are using MySql 8.* you can use REGEXP_SUBSTR in a subquery to join the two tables
SELECT a.*, b.prncode
FROM TableA a
JOIN (SELECT *, REGEXP_SUBSTR(prncode, '^[A-Z]+') as code
FROM TableB) b ON a.code = b.code
Try this below code with a join. You can use any join based on your requirement.
SELECT *
FROM TableA
INNER JOIN TableB
ON TableA.Code =
left( TableB.pnrcode, length(TableB.pnrcode) - length( reverse( concat(TableB.pnrcode, "1") ) + 0 ) + 1 );
You can use replace() to remove code from pnrcode.
If what is left is a number > 0 (MySql does implicit conversion) then join on that:
select *
from tablea a left join tableb b
on replace(b.pnrcode, a.code, '') > 0
I assume that all pnrcodes have numeric part other than 0.
See the demo.
Results:
| code | pnrcode |
| ---- | ------- |
| A | A001 |
| AB | AB001 |
| B | B001 |
| BB | |
with res as
(SELECT dbo.AlphaOnly(a.Prccode) as Prccode1,* from TableA a)
SELECT * from res join Tableb b on b.Code=res.prccode1
go
Input two table, TABLE A and TABLE B
TABLE A TABLE B
A_ID | A A_ID | B
1 | a 1 | b
2 | a1 1 | b1
3 | a2 2 | b2
Expecting Output TABLE C
TABLE C
A_ID | A | C
1 | a | b,b1 <--- Concat all rows in TABLE B with ','
2 | a1 | b2
3 | a2 | NULL <--- NULL if no matched A_ID in TABLE B
Column C finds all matched A_ID and concat All rows of B in to new TEXT field.
Can this be done only with MySQL query?
insert into TABLE_C
SELECT
A1.A_ID,
A1.A,
GROUP_CONCAT(B1.B) as 'C'
FROM `TABLE_A` A1
LEFT JOIN `TABLE_B` B1
ON A1.A_ID=B1.A_ID
GROUP BY A1.A_ID;
left join on above sql helps to get the common matching (relating) rows from two tables 'TABLE_A' and 'TABLE_B' and group by id helps to get the rows which are not not matched (not relate to each other which returns the result set for 2,a1 and 3,null). group_concat bind two columns and by default it is comma separated . If we want some other separator then only we need to used group_concat with separator statement. And also insert select helps to insert a results row into a new table 'TABLE_C' which is ofcourse need to created on prior
Try this using GROUP_CONCAT() function.
SELECT
tbla.A_ID,
tbla.A,
GROUP_CONCAT(tblb.B)
FROM `TABLE A` tbla
LEFT JOIN `TABLE B` tblb
ON tbla.A_ID=tblb.A_ID
GROUP BY tbla.A_ID;
Use group_contact to aggregate values of column B in TABLE B within a group. Insertion of values to TABLE C can be done using INSERT .. SELECT
insert into tablec
select a.a_id, a.a, group_concat(b separator ',')
from tablea a
left join tableb b on (a.a_id = b.a_id)
group by a.a_id, a.a;
I have two tables, that I would like to link by its type field.
table1
id | type
---+--------
1 | One
2 | Two
3 | Three
4 | Four
5 | Two
table2
id | type
---+------
34 | N
35 | Z
26 | Y
27 | W
And the equivalent table is (this table does not exist and cannot exist)
One = Z
Two = Y
Three = N
Four = W
And my query is
SELECT t1.type
FROM table1 t1, table2 t2
WHERE t1.type = t2.type
Probably the best solution will be change the information in one of the tables. But I cannot do that, I also can't create any store procedure.
I would like to have just one query to do this.
Any idea?
You can synthesize the relationship table in the query:
SELECT t1.id AS id1, t1.type, t2.id AS id2
FROM table1 AS t1
JOIN (
SELECT 'One' AS `long`, 'Z' AS short
UNION ALL
SELECT 'Two', 'Y'
UNION ALL
SELECT 'Three', 'N'
UNION ALL
SELECT 'Four', 'W'
) AS r ON t1.type = r.long
JOIN table2 AS t2 ON t2.type = r.short
DEMO
Probably the best solution will be change the information in one of the tables. But I cannot do that, I also can't create any store procedure. I would like to have just one query to do this.
You don't necessarily have to change the information in one of the two tables. You could create a table which contains the relationships between the two types, i.e.:
table3
type1 | type2
------+------
One | Z
Two | Y
Three | N
Four | W
Then you could write a query like this:
SELECT table1.type
FROM table1
JOIN table3
ON table1.type = table3.type1
JOIN table2
ON table3.type2 = table2.type
I am able to do an update between tables based on a count in the second table like so:
Update TableJ J
Inner Join (Select B_ID,C,S from TableC group by C,S having count=1) C
On J.C=C.C and J.S=C.S
Set T1.B_ID=T2.B_ID
The problem is my TableC does not contain S, that is stored in another table and related via B call it Table_BS (no jokes please :| ). If I didn't have to worry about count therefore I could do:
Update TableJ J
Inner Join TableC C
Inner Join TableBS BS
On J.C=C.C and C.S=BS.S
Set J.B_ID=BS.B_ID
Except the issue is, as with the original count, I only want to return B_ID when there is only one C record with an S record in TableBS.
Update:
Well this is how far I've gotten (select wise):
Select J.ID,B.B_ID
From DBJ J Inner Join LBS B Inner Join C
On J.C=C.C And (
J.S_ID = B.S_ID
or J.S_ID=B.CS_ID)
and B.B_ID=C.B_ID
Which in my case returns three records:
+----+------+
| ID | B_ID |
+----+------+
| 88 | 100 |
+----+------+
| 90 | 200 |
+----+------+
| 90 | 200 |
+----+------+
ID being the record I want to update, B_ID being the value I want to update with. In this case it turns out the count I am trying to limit is the ID column in the output, in other words I only want to update TableJ, record 88 with the value 100. TableJ record 90 turns out to have >1 result so I want to skip it. Just not sure where to put the group by or count here.
Update: Not sure why this solution remains just outside my grasp though getting closer, I can get the select to now return the ID of the record to update and the value to update with only on those records with one result like so:
Select J.ID,B.B_ID
From DBJ J Inner Join LBS B Inner Join C
On J.C=C.C And (
J.S_ID = B.S_ID
or J.S_ID=B.CS_ID)
and B.B_ID=C.B_ID group by J.ID having count(*)=1
which returns
+----+------+
| ID | B_ID |
+----+------+
| 88 | 100 |
+----+------+
And still unable to now get that to update TableJ record 88 field B_ID with the value of 100.
I am not sure if I understood correctly the problem,but here is my solution
Update TableJ J
Inner Join (
Select B_ID,TableC.C, TableBS.S
from TableC Inner Join TableBS
on TableC.B= TableBS.B
group by TableC.C,TableBS.S
having count(*)=1
) C
On J.C=C.C
Set J.B_ID=C.B_ID
This seems to have done the trick so far:
Update TableJ T1
Inner Join
(Select J.ID,B.B_ID
From TableJ J Inner Join TableBS B Inner Join TableC C
On J.C=C.C
And J.S = B.S
And B.B_ID=C.B_ID
group by J.ID having count(*)=1) T2
On T1.ID=T2.ID Set T1.B_ID=T2.B_ID
Basically solved it first with a select that returned the ID of the Update TableJ and the B_ID from TableBS where the C in TableC matched the C in TableJ and the S in TableBS matched the S in TableJ. I did a count on the results based on the ID in TableJ so that I only returned values when I got one result.
I have two tables one with ID and NAME
table 1
ID | NAME
1 | first
2 | second
3 | third
and an XREF table with ID and PARENT ID
table2
ID | PARENT ID
1 | 0
2 | 1
3 | 2
and I would like to retrieve the NAME twice like this: NAME | PARENT NAME
If it is possible to go three levels deep but with same 2-column table like this:
result table
NAME | PARENT NAME
first | NULL or EMPTY or this line the not showing at all
second | first
third | second
... then I'd like to figure that out as well.
select t1.Name, t12.Name from
table1 t1
inner join table2 t2 on t1.ID = t2.ID
inner join table1 t12 on t2.ParentID = t12.ID
This would only return 2 rows. If you want to have the first row (for ID=1) you just need to outer join instead.
Consider putting the parentid in the first table as a self-referential relationship rather than having a separate table for it.
Ex.:
table1
ID | PARENTID | NAME
---------------------------
1 NULL first
2 1 second
3 2 third
That way you would only need to join the table on itself rather than going through a 3rd table. (This is however assuming that the rows in table1 can only have a single parent, whereas your design allows one row to have multiple parents at a time)
But for your table structure, this will work:
SELECT
a.name,
c.name AS 'PARENT NAME'
FROM
table1 a
LEFT JOIN
table2 b ON a.id = b.id
LEFT JOIN
table1 c ON b.parentid = c.id
But if you made the parentid in the same table referencing id, the SQL would be reduced to this:
SELECT
a.name,
b.name AS 'PARENT NAME'
FROM
table1 a
LEFT JOIN
table2 b ON a.parentid = b.id