UPDATE query in ACCESS with AVERAGE value from other table - sql

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

Related

ORACLE - Update a value from two different columns in differente tables with a filter

I'have a little question about a query.
I have to update a column from a table where there are only record of expense(integer).
I must increase the expense of 5% if the client is from a specific state, the column of the state is in a different table and the key in common is the address.
This is my query below :
UPDATE table 1 a
SET expense_vl = (
SELECT expense*1.05 FROM table 1
LEFT JOIN table2 b ON b.ADDRESS_ID=a.ADDRESS_ID
WHERE description_state IN 'lollyland'
)
I'd recommend using a semi-join:
update table_1 a
set expense_v1 = expense * 1.05
where exists (
select null
from table2 b
where
a.address_id = b.address_id and
b.description_state = 'lollyland'
)
Althought I must add that it would help if you include the DDL for your table. We're sort of guessing at which table "description" came from.
Also, when possible, include sample input for each table and desired output. We don't need a million records, just an example that illustrates your issue.
Try below
UPDATE table1 a SET expense_vl = (SELECT expense*1.05
FROM table2 b
WHERE b.ADDRESS_ID=a.ADDRESS_ID)
WHERE description_state IN 'lollyland'
Or try with subselect:
UPDATE table1
SET expense_vl = expense*1.05
WHERE ADDRESS_ID IN (SELECT ADDRESS_ID FROM table2 WHERE description_state IN 'lollyland')
I think you need to change your query like below :
UPDATE table 1 A
SET expense_vl=expense*1.05 FROM table 1
LEFT JOIN table2 B ON B.ADDRESS_ID=A.ADDRESS_ID
WHERE B.description_state IN 'lollyland'

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

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 (****)

Inserting values generated from query into a blank column

I am trying to count the number of points (stored in table2) that are found in each polygon of table 1. The query works but I have tried to alter it to add the valus generated to a blank column in table 1.
So far it only works by appending the results to the bottom of the table. Any help? To summarise I am trying to add values generated from this query into and add them into table1. At the moment the query inserts them into the blank column in table 1, but no matched against the ID, but appended at the bottom.
INSERT INTO table1(field3)
SELECT COUNT(table2.id) AS count1
FROM table1 LEFT JOIN table2
ON ST_Contains(table1.geom,table2.geom)
GROUP BY table1.id;
The only change I made here was to switch your left join to an inner join. In the case where a geometry in table1 contains no geometries in table2, the value of field3 will stay null, so you might want to start by doing an "update table1 set field3 = 0" first (it can turn out to be a bit faster doing that in two steps depending on how many features you have and how many points each geometry has).
update table1 a
set field3 = b.count1
from
(
SELECT table1.id,
COUNT(table2.id) AS count1
FROM table1
JOIN table2
ON ST_Contains(table1.geom,table2.geom)
GROUP BY table1.id
) b
where a.id = b.id
Alternative:
update table1 a
set field3 = b.count1
from
(
SELECT table1.id,
COUNT(table2.id) AS count1
FROM table1
left JOIN table2
ON ST_Contains(table1.geom,table2.geom)
GROUP BY table1.id
) b
where a.id = b.id
Also, this site just showed up on reddit this morning. I haven't spent much time digging through it but it looks promising as (yet another) resource for learning sql (in a postgres-specific environment).
Edit: I'm starting to doubt myself with regards to the two step approach that I first posted - I think it's almost entirely wrong about the performance, so I included an alternative query.

How to get key of the maximal record in group?

I have two tables in my database, one holds the names of files, and other holds records of information described in them, inincluding sizes of sections. it can be descrived as:
Table1: id as integer, name as varchar
Table2: recid as integer primary key, file_id as integer, score as float
Between the tables there is an one-to-many link, from Table1.id to table2.file_id. What i need is for every file which name matches a certain pattern retrieve the id of the linked record with the maximum score and the score itself.
So far i have used:
SELECT name,MAX(score)
FROM Table1
LEFT OUTER JOIN Table2 ON Table2.file_id=Table1.id
WHERE name LIKE :pattern
GROUP BY name
but i cannot retrieve the id of the record in Table2 this way.
The dialect i am using is Sqlite.
What query should be used to retrieve data on the record that has maximum score for every file?
Update:
With this query, i am getting close to what i want:
SELECT name,score,recid
FROM Table1
LEFT OUTER JOIN Table2 ON file_id=id
WHERE name LIKE :pattern
GROUP BY name
HAVING score=MAX(score)
However, this leaves out the entries in the first table that have no corresponding entries in the second table out. How can i ensure they are in the end result anyway? Should i use UNION, and if so - how?
This can actually be achieved without a GROUP BY by using a brilliantly simple technique described by #billkarwin here:
SELECT name, t2.score
FROM Table1 t1
LEFT OUTER JOIN Table2 t2 ON t2.file_id = t1.id
LEFT OUTER JOIN Table2 t2copy ON t2copy.file_id = t2.file_id
AND t2.score < t2copy.score
WHERE name LIKE :pattern
AND t2copy.score IS NULL
See SQL Fiddle demo.
I think that you must use a subquery
SELECT name, recid, score
FROM Table1
LEFT OUTER JOIN Table2 ON Table2.file_id=Table1.id
WHERE name LIKE :pattern AND score = (SELECT MAX(score) FROM Table2.score)
I think the easiest way to do this is with a correlated subquery:
SELECT name, recid, score
FROM Table1 LEFT OUTER JOIN
Table2
ON Table2.file_id=Table1.id
WHERE name LIKE :pattern AND
score = (SELECT MAX(t2.score)
FROM Table1 t1 LEFT OUTER JOIN
Table2 t2
ON t2.file_id=t1.id
where t1.name = table1.name
);
Note that you need table aliases to distinguish the tables in the inner query from the outer query. I am guessing which tables the columns are actually coming from.

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