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

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

Related

Inserting values from another table into a column where values are null

I have a table A with ID's only and another table B with two columns, ID and Product Number. The ID column in table B has nulls and Product Number has Product Numbers. I would like to update table B with the ID's in column in no specific order just so that the Product Number has ID's.
I have tried to use update but that has not worked, have tried insert but it just adds the ID's in A to the bottom of the list in B. Would like to do this in Microsoft SQL.
SQL code tried:
IF OBJECT_ID('tempdb..#ProductNum') IS NOT NULL DROP TABLE #ProductNum
SELECT ID
INTO #ProductNum
FROM Products
UPDATE [ProductCatalogue] PC
SET
PC.ID = Pn.ID
FROM #ProductNum Pn
INNER JOIN
[ProductCatalogue] PC
ON Pc.ID = Pn.ID
WHERE Pc.ID IS NULL
It sounds a lot like you would be better off having the ID-Column Autoincrement, instead of giving it the IDs from table A. This is already explained in this answer.
In case you actually need the specific IDs from table A, this SO thread might help you.
Solved the issue by creating auto increment columns on each table and called it Row_ID. Then I used Row_ID to join the tables together with some logic provided by #Chris above.

Join 2 tables based on column name present in a table row

I have a table called Target where I have 5 columns:
ProductLevel
ProductName
CustomerLevel
CustomerName
Target
In another table called Products I have 3 columns:
ProductId
ProductCategory
ProductBrand
In the 3rd table called Customer I have 3 columns:
CustomerID
CustomerName
SubCustomerName
Is there a way to do a dynamic join where I select the column I will use in the JOIN based on the value that I have in the 1st table?
Example: If in the first table I have Category in ProductLevel, I'll join the table product using ProductCategory field. If I have Brand, I'll join using ProductBrand... The same happens with Customer table.
PS: I'm looking for a way to create it dynamically in a way I can add new columns to that tables without changing my code, then in the future I can have ProductSegment column in Product Table and Segment as a value in ProductLevel in Target table.
Yes, like this:
SELECT * FROM
Target t
INNER JOIN
Product p
ON
(t.ProductLevel = 'Category' AND t.??? = p.ProductCategory)
OR
(t.ProductLevel = 'Brand' AND t.??? = p.ProductBrand)
You didn't say which column in Target holds your product category/brand hence the ??? in the query above. Replace ??? with something sensible
PS; you can't do as you ask in your PS, and even this structure above is an indicator that your data model is broken. You can at least put the code in for it now even if there are no rows with t.ProductLevel = 'Segment'
Don't expect this to perform well or scale.. You might be able to improve performance by doing it as a set of UNION queries rather than OR, but you may run into issues where indexes aren't used, crippling performance

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.

In SQL Server, how can I change a column values depending on whether it contains a certain value?

Sorry if the title is a bit confusing... I'm trying to fix some data. Here goes the explanation:
Say I have two tables.
The first is a lookup table that is no longer in use.
The second has one varchar(50) column that sometimes has product names and
sometimes has product ids from the old lookup table.
The idea is to convert all the PID values in the Product table into the product names. Here's a pic i made up to help illustrate it:
The lookup table is much larger, that's just an example. So i'd guess it would be an update statement that would use the ProductsLookup.Name value if the Product value was found to be in the ProductsLookup.PID set? How would this look in SQL?
Thanks much for the help,
Carlos
You need to put inner join with both these tables "ProductsLookup" and "Products" on PID and Product column. But Product column in "Products" table is varchar so you have to apply ISNUMERIC function on this column to make sure that join works fine. below is example
UPDATE
P
SET
P.Product=PL.Name
FROM
Products P
INNER JOIN ProductsLookup PL ON PL.PID=CASE WHEN ISNUMERIC(P.Product)=1 THEN P.Product ELSE -1 END
You can do this with an update and join:
update p
set product = pl.name
from products p join
productslookup pl
on pl.pid = p.id;
A left join is not needed, because you only need to update the values that match in the lookup table.
I will caution you that performance might be an issue. The problem is the types between the two tables -- presumably pid is a number not a string. If so, you can create a computed column to change the type and an index on that column.

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?