Yii2 : Joining child table to two parent tables - yii

I have two parent tables and 1 child table in this format -
A - a_id, a_name (parent)
B - b_id, b_name (parent)
C - c_id, a_id, b_id
aid and bid are foreign keys in table C.
I am trying to create a dataProvider starting from Model A, and want to join C to the picture such that the code looks like
$query->joinWith([B,A&B.C]
But I don't know how to make C join to both A and B for the given query using Yii2 standards. Any help would be appreciated.
Thanks

To make JOIN with Yii2 through multiple DataProvider models you can use simple:
$results = $tableADataProvider->joinWith(['cRelation.bRelation')
->where([...]);
And of course in A table DataProvider you need to have relation to C table, in this example cRelation and in C table DataProvider you need to have relation to B table bRelation.
Also to mention IF you don't use any column from tables B and C in WHERE clause, but just you want to retrieve results from B then it's much better to use $tableADataProvider->with([...]) which fetches data trough another query. This way even if they are pivot tables, you will get correct count of Table A.
Worthy to note that you probably didn't get correct count (count that you wanted) if table(s) is/are pivot table(s).
(Pivot table is a table that have more than 1 record that have same unique key of other table)

Related

Join table with different primary key values

I want to join two tables with different primary key values as below
Table A
id name
1 John
2 Smith
and Table B
id name
1-x Foo
2-x Bar
I've tried using LIKE statements on my query but it won't stop executing.
SELECT * FROM A a JOIN B b ON a.id LIKE b.id +'%'
Is there any efficient way to JOIN these two tables?
If you use a query like this:
SELECT *
FROM A a JOIN
B b
ON a.id || '-x' = b.id;
Then SQLite should be able to use an index on B(id) for the query. It is worth a try.
No, there's no efficient way of joining them.
That doesn't mean it cannot be done (it can), but it probably doesn't make sense.
Primary keys are not supposed to be good looking or sexy. They are unique row identifiers. If you have a primary key with a value like that, it's because you probably want to expose it or display it somewhere; and that's not their goal.
If you need a nice looking row identifier I suggest you create a secondary unique column that could even be auto-generated.
Bottom line, keep the primary key simple.

Add new column 'Aid' to B table and link it to the increment id in A

I am new to database design. I am trying to create two tables which are linked by 'name' from A table and 'Aname' from table B. But what i want to do is creating a new increment int column 'id' as a representation for 'name' in A table and then add a new column in B called 'Aid' which is the foreign key.
My idea is to first (SQL SERVER)
SELECT row_number() over(order by A.name) id, A.* from A;
But how can I link this id to 'Aid' in B table?
Or if there is any existing statements for this question?
Thank you!
If you have the columns already defined, you can use join in an update:
update b
set b.a_id = a.a_id
from b join
a
on b.name = a.name;
I think you need to first look up how to add an auto-increment column to an existing dataset, which there are a number of resources for online. You can find one that is specific to your version of SQL Server. Then you can look into joining your B table to your A table on that. Don't add data to a table that is intended to be joined on a ROW_NUMBER result though. This is not good database design.

Joining two tables to update results in third table using like

I am trying to join two tables and update the results in the third table.
So table A is the results table and it has the columns customer number and score.
Table B has customer number and ind_code and table C has ind_code and ind_score.
So the output of the query should be such that the ind_code in table B and C should join together based on the first two digits and ind_score should be updated in Table A in the score column. Table A and Table B should be joined on the basis of customer number.
Could anyone please help. I tried multiple queries but nothing seems to work. i am using oracle sql developer
Generally, the JOIN operation mustn't cut field information but if your structure (for me not correct) is that ...
If I understand better:
UPDATE TableA
SET score =
(SELECT MAX(C.ind_score)
FROM TableC C
JOIN TableB B
ON C.ind_code = SUBSTRING(B.ind_code, 1, 2)
WHERE B.customernumber = TableA.customernumber)
I use on subquery MAX aggregate function, because I don't know if your cut of ind_code of TableB can be not unique (i.e. you have ind_code 5555 and 5554)

Update a field from one table to another, involving a 3 table join

I have a table I need to update the price field in. I need to update this field from a different price field from a different table. The only way I can get to the required table for the update is by joining another table into this query.
So in all I need to join 3 tables in the update.
Table A has the price field that needs to be updated. In this table I have the foreign key of the product.
Table A structure
-PK_TABLE_A,
-FK_TABLE_B,
-ITEM_COST,
-ITEM_PRICE (needs to be updated from Table C)
Table B is the product table which has the PK of the product. This table is used to access Table C.
I also need to filter Table B to only update a certain stock type.
Table B structure
-PK_TABLE_B,
-FK_TABLE_C,
-DESCRIPTION,
-QUANTITY,
-ITEM_TYPE (a string that needs to be added in where clause to only update records with certain type).
Table C has a foreign key back to Table B. It also contains the price field that I need to use to update the price field in table A
Table C structure
-PK_TABLE_C,
-FK_TABLE_B,
-PRICE (this is the field that I need to use to update the price field in table A)
-USED_DATE,
-ID
The DBMS I am using is Firebird.
I have tried to use sub queries to no avail. I regularly use a sub-select when using two tables to update, so something like
UPDATE table1 AS t1
SET t1.FK = (select table2.PK
FROM table2 INNER JOIN
table1
ON table2.FK = table2.PK
WHERE table2.name = t1.name)
I'm just struggling to use the same technique with a 3rd table incorporated.
I am not even sure if this is the correct way to go about this situation. I have looked on google, but most examples I have come across don't utilise the 3rd table.
Any help would be appreciated.
**edited to included more detail on table structure.
are you able to show us the table structures in more detail?
if both tableA and tableC have a foreign key that points back to tableB I don't think you need to include a three table join. you just need to
update tableA set ITEM_PRICE = SELECT(PRICE FROM TableC WHERE
TableA.FK_TABLE_B = TableC.FK_TABLE_B;
unless I'm missing something?
edited to reflect a better understanding of the problem
alright, I think I've got it this time:
update tableA set price =
(select price from tableC where tableA.fk_tableB = tableC.fk_tableB) where
(Select item_type from tableB where tableB.pk_tableB = tableA.fk_tableB) =
'$itemTypeVariable';
edited again with a better understanding of the problem

How do I (quickly) collate IDs from various tables?

I have three denormalized tables that I have to take at face value (data comes from some external resource). The three tables have different definitions, but they each describe the same object from different perspectives.
object1 A B
object2 A
object3 B C
object4 C
The only commonality between these tables is their primary key. I can corral the IDs together using SELECT UNION SELECT, but the query seems relatively slow, even when each table has its PK field indexed. I could create a view to abstract this query, vw_object_ids, but it performs at the same speed. I thought I could add an index to materialize the view, but in SQL Server 2005, you can't index views with UNIONs.
What I want is to have a master index of IDs be in sync with with the underlying data, which may get updated or deleted whenever. I guess I could accomplish this indefinitely with a crazy set of triggers or just settle for the speed of the unindexed view. But I just wanted to make sure I'm not missing any options or if this scenario has a name or is indicative of a pattern.
Thoughts?
Create a master table that contains only the ID:
CREATE TABLE master (ID INT NOT NULL PRIMARY KEY)
and make all three tables to refer to that master table with ON DELETE CASCADE.
To populate the table for the first time, issue
INSERT
INTO master
SELECT id
FROM a
UNION
SELECT id
FROM b
UNION
SELECT id
FROM c
To populate the table on a regular basis, create a trigger on each of three tables.
This trigger should try to insert the new ID to master and silently fail on PRIMARY KEY violation.
To query, use:
SELECT *
FROM master m
LEFT OUTER JOIN
a
ON a.id = m.id
LEFT OUTER JOIN
b
ON b.id = m.id
LEFT OUTER JOIN
c
ON c.id = m.id
This will use indexes efficienty.
To delete, use:
DELETE
FROM master
WHERE id = #id
This will fire ON DELETE CASCADE and delete records from all three tables if any.
Why not just do an outer join and then coalesce the columns from the component tables?