When using UPDATE and SET with SQL rows appear to be missing - sql

When I run the query below :
SELECT COUNT(x.objectID)
FROM db0..table0 as t
INNER JOIN db1..table1 as x ON t.objID = x.slaveID
INNER JOIN db1..table2 as table2 ON table2.sourceID = x.objectID
WHERE (****)
I get 268'466 results. However when I update and add a column to db0..table0 with x.objectID as follows, I get 145'346 of these items into my db0.table0
ALTER TABLE db0..table0 ADD new_objID bigint;
UPDATE db0..table0
SET db0..table0.new_objID = x.objectID
FROM db0..table0 as t
INNER JOIN db1..table1 as x ON t.objID = x.slaveID
INNER JOIN db1..table2 as table2 ON table2.sourceID = x.objectID
WHERE (****)
Can anyone see what is going wrong? The only difference between the queries is the first line in the first query is replaced with the first two lines in the second query.
To count the number of new values that end up in my table I use,
SELECT COUNT(new_objID)
FROM db0..table0
This should return all the none NULL instances of new_objID.
EDIT
So the table structures are
table0
table0_ID
table1
table1_ID
other_table1_ID
value
table0 and table1 are linked by table0_ID and table1_ID in a many to one relationship. One table0_ID corresponds to many table1_ID. I realised that table2 was no longer necessary - in the past I wanted information from this table but not any longer.
Effectively all I am trying to do is add the other_table1_ID entry, which corresponds to the smallest entry of value for each group of table1_ID into table0.
The issue is the discrepancy between these queries suggest I am doing something wrong I just can't work out what.
QUERY ONE
SELECT COUNT(table1.table1_ID)
FROM db0..table0 as table0
INNER JOIN db1..table1 as table1
ON table0.table0_ID = table1.table1_ID
WHERE table1.value IN (SELECT MIN(value)
FROM db1..table1 as new_table1
WHERE new_table1.table1_ID = table1.table1_ID)
QUERY TWO
ALTER TABLE db0..table0 ADD newID bigint
UPDATE db0..table0
SET db0..table0.newID = table1.other_table1_ID
FROM db0..table0 as table0
INNER JOIN db1..table1 as table1
ON table0.table0_ID = table1.table1_ID
WHERE table1.value IN (SELECT MIN(value)
FROM db1..table1 as new_table1
WHERE new_table1.table1_ID = table1.table1_ID)

UPDATE: after some discussion and question update by OP we came to the conclusion that conditions in both queries should be changed to the following:
new_table1.table1_ID = table1.table1_ID should instead be table0.table0_ID = new_table1.table1_ID
then both SELECT queries (original and the one which counts the newID field) return same count of 206146 records.
In the first query you do COUNT(x.objectID) but in the UPDATE call you SET db0..table0.new_objID = x.objID .
Notice, different column names: x.objectID in the first case and x.objID in the second.
Change your second query to the following:
UPDATE db0..table0
SET db0..table0.new_objID = x.objectID
FROM db0..table0 as t
INNER JOIN db1..table1 as x
ON t.objID = x.slaveID
INNER JOIN db1..table2 as table2
ON table2.sourceID = x.objectID
WHERE (****)

Related

UPDATE query in ACCESS with AVERAGE value from other table

I have these two simple access tables.
Table 1 consists of an Item description and weight column. Item description is not unique as weight slightly varies.
Table 2 is designed to hold the average weight of the items in table 1. In this table the item description is unique.
I cannot make the UPDATE query in ACCESS work. It says the query does not include weight as part of an aggregate function.
When I attempt to add a GROUP BY clause, it still does not work due to syntax errors..
Anyone have an idea as to what might be the issue?
Here is the query:
UPDATE TABLE2
INNER JOIN TABLE1 ON TABLE2.DESCRIPTION = TABLE1.DESCRIPTION
SET TABLE2.WEIGHT = AVG(TABLE1.WEIGHT)
UPDATE t2
SET t2.WEIGHT = t1.AVG_WEIGHT
FROM TABLE2 t2
INNER JOIN (select TABLE1.DESCRIPTION,AVG(TABLE1.WEIGHT) as AVG_WEIGHT
from TABLE1
group by TABLE1.DESCRIPTION) as t1
on TABLE2.DESCRIPTION = TABLE1.DESCRIPTION
There is simpler way here-
You need to create a staging or inter-mediate table to calculate the average.
You must create a new table t3,from query-
select TABLE1.DESCRIPTION,AVG(TABLE1.WEIGHT) as AVG_WEIGHT
from TABLE1
group by TABLE1.DESCRIPTION
And then you can use it in update query
UPDATE TABLE2
INNER JOIN TABLE3 ON TABLE3.DESCRIPTION = TABLE2.DESCRIPTION
SET TABLE3.WEIGHT = TABLE2.WEIGHT

Set the value in temp table while checking two columns

I'm using SQL Server: I need to update a column(phone number) in temp table based on checking two column values one after another. Here is my current version of code: Basically what it does is, it sets the value of column in the temp table based on where it match the join condition.
update r
set t.phone_number = tb.phone_number
from #temptable t
inner join phone_number_records tb
on t.id = tb.id
and 1 = tb.is_this_valid
Now I need to check another column value (ready_to_accept_new) in phone_number_records table and update the phone_number field in temp table as per ready_to_accept_new value. If ready_to_accept_new is equal to "1" and "id" of temptable matches with "id" of phone_number_records, i need to set phone_number value in the temptable with the matching record phone_number(in phone_number_records table). If there are no matching records on this criteria, we need to update the temp table record as previous.( from matching is_this_valid column value "1" record).
Can someone please let me know how to solve this one? Thanks in advance!
In addition to the answer supplied by John, it can be done with IF..ELSE block
if exists(select * from #temptable t
inner join phone_number_records tb
on t.id = tb.id
and 1 = tb.ready_to_accept_new )
update r
set t.phone_number = tb.phone_number
from #temptable t
inner join phone_number_records tb
on t.id = tb.id
and 1 = tb.ready_to_accept_new
else
update r
set t.phone_number = tb.phone_number
from #temptable t
inner join phone_number_records tb
on t.id = tb.id
and 1 = tb.is_this_valid
Quickest way is to join to your table twice.
Use a left join for the per ready_to_accept_new value join and then use a case statement to see if this exists.
IE:
update r
set t.phone_number =
CASE
WHEN tb_1.id IS NOT NULL THEN tb_1.phone_number
ELSE tb.phone_number
END
from #temptable t
inner join phone_number_records tb
on t.id = tb.id
and 1 = tb.is_this_valid
left join phone_number_records tb_1
on t.id = tb.id
and 1 = tb.per ready_to_accept_new value
apologies for the formatting!

How to update Two Columns at the same time with different queries

I have this after insert trigger which updates two different columns based on a join. Basically it turns an Id into a value. This works fine except when one of the Ids does not match (ie, it's zero for the default) Then neither is updated. If the join fails, it should just insert null.
CREATE TRIGGER [AfterHistoryInsert]
ON [Jet].[HistoryEntity]
FOR INSERT
AS
BEGIN
Update t1 Set t1.OldValue = t2.Value, t1.NewValue = t3.Value
From Jet.HistoryEntity t1
join Jet.LookupListItemEntity t2 on Cast(t1.OldValue as int) = t2.Id
join Jet.LookupListItemEntity t3 on Cast(t1.NewValue as int) = t3.Id
inner join inserted i on i.Id = t1.Id
where t1.FieldName like '%Id'
END
Greg
Try left outer join instead join
If you are updating into a bigger table, one of the suggestion will be:
- Selecting all the columns that you want to update(In your case Value) into temp table
- Update Statement by using left outer join to temp table.

SQL command to compare results is not working [duplicate]

I want to update a column in a table making a join on other table e.g.:
UPDATE table1 a
INNER JOIN table2 b ON a.commonfield = b.[common field]
SET a.CalculatedColumn= b.[Calculated Column]
WHERE
b.[common field]= a.commonfield
AND a.BatchNO = '110'
But it is complaining :
Msg 170, Level 15, State 1, Line 2
Line 2: Incorrect syntax near 'a'.
What is wrong here?
You don't quite have SQL Server's proprietary UPDATE FROM syntax down. Also not sure why you needed to join on the CommonField and also filter on it afterward. Try this:
UPDATE t1
SET t1.CalculatedColumn = t2.[Calculated Column]
FROM dbo.Table1 AS t1
INNER JOIN dbo.Table2 AS t2
ON t1.CommonField = t2.[Common Field]
WHERE t1.BatchNo = '110';
If you're doing something silly - like constantly trying to set the value of one column to the aggregate of another column (which violates the principle of avoiding storing redundant data), you can use a CTE (common table expression) - see here and here for more details:
;WITH t2 AS
(
SELECT [key], CalculatedColumn = SUM(some_column)
FROM dbo.table2
GROUP BY [key]
)
UPDATE t1
SET t1.CalculatedColumn = t2.CalculatedColumn
FROM dbo.table1 AS t1
INNER JOIN t2
ON t1.[key] = t2.[key];
The reason this is silly, is that you're going to have to re-run this entire update every single time any row in table2 changes. A SUM is something you can always calculate at runtime and, in doing so, never have to worry that the result is stale.
Try it like this:
UPDATE a
SET a.CalculatedColumn= b.[Calculated Column]
FROM table1 a INNER JOIN table2 b ON a.commonfield = b.[common field]
WHERE a.BatchNO = '110'
Answer given above by Aaron is perfect:
UPDATE a
SET a.CalculatedColumn = b.[Calculated Column]
FROM Table1 AS a
INNER JOIN Table2 AS b
ON a.CommonField = b.[Common Field]
WHERE a.BatchNo = '110';
Just want to add why this problem occurs in SQL Server when we try to use alias of a table while updating that table, below mention syntax will always give error:
update tableName t
set t.name = 'books new'
where t.id = 1
case can be any if you are updating a single table or updating while using join.
Although above query will work fine in PL/SQL but not in SQL Server.
Correct way to update a table while using table alias in SQL Server is:
update t
set t.name = 'books new'
from tableName t
where t.id = 1
Hope it will help everybody why error came here.
MERGE table1 T
USING table2 S
ON T.CommonField = S."Common Field"
AND T.BatchNo = '110'
WHEN MATCHED THEN
UPDATE
SET CalculatedColumn = S."Calculated Column";
UPDATE mytable
SET myfield = CASE other_field
WHEN 1 THEN 'value'
WHEN 2 THEN 'value'
WHEN 3 THEN 'value'
END
From mytable
Join otherTable on otherTable.id = mytable.id
Where othertable.somecolumn = '1234'
More alternatives here.
Seems like SQL Server 2012 can handle the old update syntax of Teradata too:
UPDATE a
SET a.CalculatedColumn= b.[Calculated Column]
FROM table1 a, table2 b
WHERE
b.[common field]= a.commonfield
AND a.BatchNO = '110'
If I remember correctly, 2008R2 was giving error when I tried similar query.
I find it useful to turn an UPDATE into a SELECT to get the rows I want to update as a test before updating. If I can select the exact rows I want, I can update just those rows I want to update.
DECLARE #expense_report_id AS INT
SET #expense_report_id = 1027
--UPDATE expense_report_detail_distribution
--SET service_bill_id = 9
SELECT *
FROM expense_report_detail_distribution erdd
INNER JOIN expense_report_detail erd
INNER JOIN expense_report er
ON er.expense_report_id = erd.expense_report_id
ON erdd.expense_report_detail_id = erd.expense_report_detail_id
WHERE er.expense_report_id = #expense_report_id
Another approach would be to use MERGE
;WITH cteTable1(CalculatedColumn, CommonField)
AS
(
select CalculatedColumn, CommonField from Table1 Where BatchNo = '110'
)
MERGE cteTable1 AS target
USING (select "Calculated Column", "Common Field" FROM dbo.Table2) AS source ("Calculated Column", "Common Field")
ON (target.CommonField = source."Common Field")
WHEN MATCHED THEN
UPDATE SET target.CalculatedColumn = source."Calculated Column";
-Merge is part of the SQL Standard
-Also I'm pretty sure inner join updates are non deterministic..
Similar question here where the answer talks about that
http://ask.sqlservercentral.com/questions/19089/updating-two-tables-using-single-query.html
I think, this is what you are looking for.
UPDATE
Table1
SET
Table1.columeName =T1.columeName * T2.columeName
FROM
Table1 T1
INNER JOIN Table2 T2
ON T1.columeName = T2.columeName;
I had the same issue.. and you don't need to add a physical column.. cuz now you will have to maintain it..
what you can do is add a generic column in the select query:
EX:
select tb1.col1, tb1.col2, tb1.col3 ,
(
select 'Match' from table2 as tbl2
where tbl1.col1 = tbl2.col1 and tab1.col2 = tbl2.col2
)
from myTable as tbl1
Aaron's approach above worked perfectly for me. My update statement was slightly different because I needed to join based on two fields concatenated in one table to match a field in another table.
--update clients table cell field from custom table containing mobile numbers
update clients
set cell = m.Phone
from clients as c
inner join [dbo].[COSStaffMobileNumbers] as m
on c.Last_Name + c.First_Name = m.Name
Those who are using MYSQL
UPDATE table1 INNER JOIN table2 ON table2.id = table1.id SET table1.status = 0 WHERE table1.column = 20
Try:
UPDATE table1
SET CalculatedColumn = ( SELECT [Calculated Column]
FROM table2
WHERE table1.commonfield = [common field])
WHERE BatchNO = '110'

Updating row of table Using data from multiple columns of another table

I have following table which I want to update using another table, given below.alt text http://img94.imageshack.us/img94/4602/leisureoriginal.png
I want to update Null values of above given table using following table on the basis of ProductId.
alt text http://img264.imageshack.us/img264/512/datatable2.png
The updated table should be like this.
alt text http://img690.imageshack.us/img690/9585/updatedtable.png
I have mentioned ProductId in these table just for example. I don't know exact ProductId. It could be any ProductId.
I know FieldId and FieldValue in advance in 2nd table.
Can I do this in one UPDATE statement for all columns.
In SQL Server, the PIVOT keyword turns rows into columns. We need two PIVOTs, one for FieldId and one for FieldValue. The ;WITH keyword (which is preceded by a semicolon to distinguish it from the unrelated WITH ROLLUP command) allows us to use create "temporary views" which we use later in the UPDATE statement.
;WITH FieldIds AS (SELECT * FROM (SELECT ProductId, FieldId FROM ProductFields) A
PIVOT (MAX(FieldId) FOR FieldId IN ([50], [55], [60])) AS B),
FieldValues AS (SELECT * FROM ProductFields
PIVOT (MAX(FieldValue) FOR FieldId IN ([50], [55], [60])) AS C)
UPDATE Products
SET
RatingId = FieldIds.[50],
Rating = FieldValues.[50],
LeisureId = FieldIds.[55],
Leisure = FieldValues.[55],
SpaId = FieldIds.[60],
Spa = FieldValues.[60]
FROM Products
INNER JOIN FieldIds ON FieldIds.ProductId = Products.ProductId
INNER JOIN FieldValues ON FieldValues.ProductId = Products.ProductId
In SQL Server, an UPDATE statement allows a FROM clause with JOINS. For example, this query would update the Rating field:
UPDATE p
SET p.Rating = pf.FieldValue
FROM Products p
INNER JOIN ProductField pf
ON pf.ProductId = p.ProductId
WHERE pf.FieldId = 50
You could copy this query for the other fields. It's also possible to update more fields in query, but that seems unnecessary in this case.
You will first need to transform your second table so that it contains only one row per ProductID.
SELECT t1.ProductID, t1.FieldID AS RatingID, t1.FieldValue AS Rating,
t2.FieldID AS LeisureID, t2.FieldValue AS Leisure, etc.
FROM SecondTable t1
LEFT OUTER JOIN SecondTable t2
ON t1.ProductID = t2.ProductID
AND t2.FieldValue = 55
LEFT OUTER JOIN SecondTable t3
ON t1.ProductID = t3.ProductID
AND t3.FieldValue = 60
WHERE t1.FieldValue = 50
Then you can update all columns in the first table from this table in one update query. Note that you could make the above a View of the Second table so this would be easier to use later. (We'll call it SecondTableView for now; incidentally it has the exact form of the first table now).
UPDATE FirstTable
SET RatingID = t1.RatingID, Rating = t1.Rating, etc.
FROM SecondTableView t1
WHERE FirstTable.ProductID = t1.ProductID
The issue with this approach is that you must know all of the possible Fields for each Product ahead of time but that is pretty much required anyway because of the table schema being fixed.
Maybe something like this:
Update T1
Set T1.RatingID = T2.FieldID,
T1.Rating = T2.FieldValue
From Table1 T1
Inner JOin Table2 T2
On T1.ProductID = T2.ProductID
Where T2.FieldID = 50
To edit all the columns at once, you would need to use subqueries:
Update T1
Set T1.RatingID = (Select T2.FieldID
From Table2 T2
Where T2.FieldID = 50
And T2.ProductID = T1.ProductID)
From Table1 T1