updating values of a table from another table through a join changes all values to 1 single value - sql

I have 3 tables: raw_sales, sales and details. raw_sales is being populated using COPY from a txt file. All the fields in raw_sales are either string or text. After importing, we run an sql to populate sales and details. There is a foreign key (sale_id) in details. Here's a sample INSERT command that we use to populate sales and details.
INSERT INTO sales (source, source_identifier)
(SELECT DISTINCT
'FOO' AS source,
"identifier" AS source_identifier
FROM raw_sales
LEFT JOIN sales
ON sales.source_identifier = raw_sales.identifier
AND sales.source = 'FOO'
WHERE sales.id IS NULL
AND identifier IS NOT NULL);
INSERT INTO details (sale_id, description)
(SELECT DISTINCT
sales.id AS sale_id,
"improvements" as description
FROM raw_sales
JOIN sales
ON sales.source_identifier = raw_sales.identifier
AND sales.source = 'FOO'
LEFT JOIN details AS existing
ON existing.sale_id = sales.id
WHERE existing.id IS NULL
AND "improvements" != '');
This seems to work fine. After this, there's another sql that's being ran to update existing tables. The query is as follows
UPDATE details SET
description = "improvements"
FROM raw_sales
JOIN sales
ON sales.source_identifier = raw_sales.identifier
AND sales.source = 'FOO'
JOIN details AS existing
ON existing.sale_id = sales.id
WHERE existing.id IS NOT NULL;
This query updates all rows in the details table to a single value, the first non-empty value from raw_sales table. How can I change the above sql so that it updates the existing records in the details table?

There are several problems with your query:
if details.id is a primary key (field id typically is), then what is the point in comparing it to NOT NULL? You're not using any left joins, there is no way it could possibly be NULL if it truly is an identifier.
UPDATE table t SET ... FROM ... requires linking the table t with something on the FROM section, but you're not, therefore each row of table will be updated to any single random row from the FROM results.
Perhaps you want to do this:
UPDATE details SET
description = "improvements"
FROM raw_sales
JOIN sales ON (sales.source_identifier = raw_sales.identifier AND sales.source = 'FOO')
JOIN details AS existing ON (existing.sale_id = sales.id)
WHERE existing.id = details.id;

Related

SQL-Oracle: Updating table multiple row based on values contained in the same table

I have one table named: ORDERS
this table contains OrderNumber's which belong to the same person and same address lines for that person.
However sometimes the data is inconsistent;
as example looking at the table screenshot: Orders table with bad data to fix -
you all can noticed that orderNumber 1 has a name associated to and addresses line1-2-3-4. sometimes those are all different by some character or even null.
my goal is to update all those 3 lines with one set of data that is already there and set equally all the 3 rows.
to make more clear the result expected should be like this:
enter image description here
i am currently using a MERGE statement to avoid a CURSOR (for loop )
but i am having problems to make it work
here the SQL
MERGE INTO ORDERS O USING
(SELECT
INNER.ORDERNUMBER,
INNER.NAME,
INNER.LINE1,
INNER.LINE2,
INNER.LINE3,
INNER.LINE4
FROM ORDERS INNER
) TEMP
ON( O.ORDERNUMBER = TEMP.ORDERNUMBER )
WHEN MATCHED THEN
UPDATE
SET
O.NAME = TEMP.NAME,
O.LINE1 = TEMP.LINE1,
O.LINE2 = TEMP.LINE2,
O.LINE3 = TEMP.LINE3,
O.LINE4 = TEMP.LINE4;
the biggest issues i am facing is to pick a single row out of the 3 randomly - it does not matter whihc of the data - row i pick to update the line/s
as long i make the records exaclty the same for an order number.
i also used ROWNUM =1 but it in multip[le updates will only output one row and update maybe thousand of lines with the same address and name whihch belong to an order number.
order number is the join column to use ...
kind regards
A simple correlated subquery in an update statement should work:
update orders t1
set (t1.name, t1.line1, t1.line2, t1.line3, t1.line4) =
(select t2.name, t2.line1, t2.line2, t2.line3, t2.line4
from orders t2
where t2.OrderNumber = t1.OrderNumber
and rownum < 2)

Sql Server - Update multiple rows based on the primary key (Large Amount of data)

struggling with this one, quite a lengthy description so ill explain best I can:
I have a table with 12 columns in, 1 being a primary key with identity_insert, 1 a foreign key , the other 10 being cost values, ive created a statement to group them into 5 categories, shown below:
select
(ProductID)ProjectID,
sum(Cost1)Catagory1,
sum(Cost2)Catagory2,
sum(Cost3 + Cost4 + Cost5 + Cost6 + Cost7) Catagory3,
sum(Cost 8 + Cost 9)Catagory4,
sum(Cost10)Catagory5
from ProductTable group by ProductID
ive changed the names of the data to make it more generic, they aren't actually called Cost1 etc by the way ;)
the foreign key can appear multiple times (ProductID) so in the above query the related fields are calculated together based upon this... Now what ive been trying to do is put this query into a table, which i have done successfully, and then update the data via a procedure. the problem im having is that all the data in the table is overwritten by row 1 and when theres is thousands of rows this is a problem.
I have also tried putting the above query into a view and the same result... any suggestions would be great :)
update NewTable set
ProductID = (ProductView.ProductID ),
Catagory1 = (ProductView.Catagory1 ),
Catagory2 = (ProductView.Catagory2 ),
Catagory3 = (ProductView.Catagory3 ),
Catagory4 = (ProductView.Catagory4 ),
Catagory5 = (ProductView.Catagory5 )
from ProductView
I need something along the lines like above.... but one that doesn't overwrite everything with row 1 haha ;)
ANSWERED BY: Noman_1
create procedure NewProducts
insert into NewTable
select ProductID.ProductTable,
Catagory1.ProductView,
Catagory2.ProductView,
Catagory3.ProductView,
Catagory4.ProductView,
Catagory5.ProductView
from ProductView
inner join ProductTable on ProductView.ProductID = ProductTable.ProductID
where not exists(select 1 from NewTable where ProductView.ProductID = NewTable.ProductID)
above procedure locates the new Product that has been created within a view, the procedure query detects that there is a Product that is not located in the NewTable and inserts it via the procedure
As far as i know, and since you want to update all the products in the table, and each product uses all the sums of the product itself from origin, you actually need to update each row 1 by 1, and as consecuence when you do an update like the next, its your only main way
update newtable
set category1 = (select sum(cost1) from productTable where productTable.productId = newtable.ProductID),
category2 = (select sum(cost2) from productTable where productTable.productId = newtable.ProductID),
etc..
Keep in mind that if you have new products, they wont get inserted with the update, you would need like this in order to add them:
Insert into newtable
Select VALUES from productTable a where productId not exists(select 1 from newTable b where a.ProductId = b.ProductId);
A second way, and since you want allways to update all the data, is to simply truncate and do a insert select right after.
Maybe on an Oracle, you would be albe to use a MERGE but im unaware if it would really improve anything.
I asume that simply having a view would not work due the amount of data you state you have.
EDIT, I never knew that the MERGE STATMENT is actually avaiable on SQL Server 2008 and above, with this single statment you could do an UPDATE/INSERT on all but it's efficiency is unknown to me, you may want to test it with your high amount of data:
MERGE newtable AS TARGET
USING select ProductId, sum(cost1) cat1, sum(cost2) cat2 ...
FROM productTable Group by ProductId AS SOURCE
ON TARGET.ProductId = SOURCE.ProductID
WHEN MATCHED
THEN UPDATE SET TARGET.category1 = cat1, TARGET.category2 = cat2...
WHEN NOT MATCHED
THEN INSERT (ProductId, category1, category2,...)
VALUES (SOURCe.ProductId, SOURCE.cat1, SOURCE.cat2...);
More info about merge here:
http://msdn.microsoft.com/library/bb510625.aspx
The example at the end may give you a good overview of the sintax
You haven't given any join condition. SQL Server cannot know that you meant to update rows matched by productid.
update NewTable set
ProductID = (ProductView.ProductID ),
Catagory1 = (ProductView.Catagory1 ),
Catagory2 = (ProductView.Catagory2 ),
Catagory3 = (ProductView.Catagory3 ),
Catagory4 = (ProductView.Catagory4 ),
Catagory5 = (ProductView.Catagory5 )
from NewTable
join ProductView pv on NewTable.productid = pv.productid
You don't need a view. Just past the view query to the place where I said ProductView. Of course, you can use a view.

SQL insert data into a table from another table

I'm having a problem trying to insert some values into a table. I made an empty table with the fields
id(primary key)
association_id
resource_id
I have another table with
resource_id
association_id
and another one with
id(coresponding to the association_id in the former one)
image
I want to insert the resource_id and association_id from the first populated table, where the image field of the coresponding id from the last table is not empty.
I tried this:
INSERT IGNORE INTO `logo_associations` (``,`association_id`,`resource_id`)
SELECT
``,
`a`.`association_id`,
`a`.`resource_id`
FROM doc24_associations_have_resources a
Join doc24_associations An on a.association_id = An.id
WHERE An.image<>''
but it does not work
Try this:
INSERT INTO logo_associations (association_id, resource_id)
SELECT a.association_id
,a.resource_id
FROM doc24_associations_have_resources a
LEFT JOIN doc24_associations an ON a.association_id = an.id
WHERE an.image IS NULL -- check for null with left join
This is valid for SQL Server. You do not need to select and insert the first column as it is an identity as you mention.
My experience is based on SQL Server but the SQL may be very similar
INSERT INTO DestinationTable
(association_id, resource_id)
SELECT LNK.assocication_id,
LNK.resource_id
FROM LinkTable AS LNK
INNER JOIN ImageTable AS IMG ON IMG.id = LNK.association_id
AND IMG.image IS NOT NULL
Above I assume the following:
Tables are named DestinationTable, LinkTable, and ImageTable respectively
In DestinationTable the primary key (id) is auto generated

Advanced sql query

I have two tables in a sql database, I am trying to update a column from my committed table (committedtbl) with values from my vendor table (vendortbl) based on a common column from both tables.
There is a column with the vendor identification number (vendorno) in both tables, I tried adding the vendor description (vendorname) column from the vendortbl to the committedtbl but there are no values in it.
I need to insert values into the vendorname based on the corresponding numbers from vendorno... How do I accomplish this?
The vendorname column already exists in my committedtbl.
I have tried this, but got an error:
update v_vendorname
set v_vendorname = v_vendorno
from vendortbl vt
where v_vendorno = vt.v_venkey
update committedtbl
set c.vendorname = v.vendorname
from committedtbl c
inner join vendortbl v on v.vendorno = c.vendorno

Updating a table by referencing another table

I have a table CustPurchase (name, purchase) and another table CustID (id, name).
I altered the CustPurchase table to have an id field. Now, I want to populate this newly created field by referencing the customer ids from the CustID table, using:
UPDATE CustPurchase
SET CustPurchase.id = CustID.id
WHERE CustPurchase.name = CustID.name;
I keep getting syntax errors!
I believe you are after the useful UPDATE FROM syntax.
UPDATE CustPurchase SET id = CI.id
FROM
CustPurchase CP
inner join CustID CI on (CI.name = CP.name)
This might have to be the following:
UPDATE CustPurchase SET id = CI.id
FROM
CustID CI
WHERE
CI.name = CustPurchase.name
Sorry, I'm away from my Postgres machine; however, based upon the reference, it looks like this is allowable. The trouble is whether or not to include the source table in the from_list.
Joining by name is not an ideal choice, but this should work:
UPDATE custpurchase
SET id = (SELECT c.id
FROM CUSTID c
WHERE c.name = custpurchase.name)
The caveat is that if there's no match, the value attempting to be inserted would be NULL. Assuming the id column won't allow NULL but will allow duplicate values:
UPDATE custpurchase
SET id = (SELECT COALESCE(c.id, -99)
FROM CUSTID c
WHERE c.name = custpurchase.name)
COALESCE will return the first non-NULL value. Making this a value outside of what you'd normally expect will make it easier to isolate such records & deal with appropriately.
Otherwise, you'll have to do the updating "by hand", on a name by name basis, to correct instances that SQL could not.