Reputation: 27
I am trying to modify records in a column of one table whenever I meet some condition in another table.
Specifically, whenever there is a 'y' in the RobotComRein.Reinforcement table/column, I want to add a 1 to the table/column: RobotComYN.Yesses.
Furthermore, both tables have columns called "RobotID" and "Command" and I would like to make the change only when the following condition is met:
RobotComRein.RobotID = RobotComYN.RobotID AND RobotComRein.Command = RobotComYN.Command
I have tried messing around with the following SQL statement.
UPDATE RobotComYN
SET Yesses = Yesses + 1
WHERE RobotComRein.Reinforcement IN (
SELECT RobotComRein.Reinforcement
FROM RobotComRein
WHERE RobotComRein.Reinforcement = 'y'
AND RobotComRein.RobotID = RobotComYN.RobotID
AND RobotComRein.Command = RobotComYN.Command
);
I receive the following error message: "no such column: RobotComRein.Reinforcement"
Upvotes: 0
Views: 44
Reputation: 3884
It's all about context and the order that tables are referenced. You are trying to reference another table from the UPDATE's WHERE clause, but there is no relationship between the two tables at that level. It is okay to reference the "outer" table from the nested query inside the parenthesis, but not vice versa. In other words, you are updating RobotComYN
, so you can't directly reference RobotComRein
table columns in the WHERE clause.
See How to UPDATE a SQLITE Column with an INNER JOIN on TWO FIELDS. The following are customized statements based on the accepted answer:
UPDATE RobotComYN
SET Yesses = Yesses + 1
WHERE EXISTS (SELECT RobotComRein.RobotID
FROM RobotComRein
WHERE (RobotComRein.RobotID = RobotComYN.RobotID)
AND (RobotComRein.Command = RobotComYN.Command)
AND RobotComRein.Reinforcement = 'y'
);
Notice that the inner select of the original answer was SELECT *
, but it is unnecessary to return all columns just to test for existence of a matching row. Only a single column is needed and is more efficient.
UPDATE RobotComYN
SET Yesses = Yesses + 1
WHERE (RobotID, Command) IN (
SELECT RobotComRein.RobotID, RobotComRein.Command
FROM RobotComRein
WHERE RobotComRein.Reinforcement = 'y');
The following update sets the new value from an aggregate query that counts the rows of the related table:
UPDATE RobotComYN
SET Yesses = Yesses + (
SELECT Count(RobotComRein.RobotID) AS increase
FROM RobotComRein
WHERE RobotComRein.RobotID = RobotComYN.RobotID
AND RobotComRein.Command = RobotComYN.Command
AND RobotComRein.Reinforcement = 'y')
WHERE (RobotID, Command) IN (
SELECT RobotComRein.RobotID, RobotComRein.Command
FROM RobotComRein
WHERE RobotComRein.Reinforcement = 'y');
I was originally thinking that a WITH statement would eliminate the need for multiple subqueries, but that flawed thinking eventually gets back to the fact that the sqlite UPDATE statement does not support direct joins on the updated table. The WITH statement still does not eliminate the need to redefine the "join" columns for both sub-queries--it does not simplify the query. About the only benefit to the WITH statement is that the WITH query will be executed only once which applies any filters and aggregates.
WITH filtered AS (
SELECT RobotID, Command, Count(*) AS increase
FROM RobotComRein
WHERE RobotComRein.Reinforcement = 'y'
GROUP BY RobotID, Command)
UPDATE RobotComYN
SET Yesses = Yesses + (
SELECT increase
FROM filtered
WHERE filtered.RobotID = RobotComYN.RobotID
AND filtered.Command = RobotComYN.Command)
WHERE (RobotID, Command) IN (
SELECT filtered.RobotID, filtered.Command
FROM filtered);
Upvotes: 1