MYSQL Update with 2 INNER JOINs hangs - mysql

I am trying to update a field in my table based on if it exists in two join tables.
update quotes
inner join collection_records ON quotes.id <> collection_records.record_id
inner join subcollection_records ON quotes.id <> subcollection_records.record_id
set quotes.status_id = 1
where collection_records.type = 'Quote'
or subcollection_records.type = 'Quote'
this query runs, but hangs. If I remove on inner join it works, but I need to check both join tables for the existance of the quote id.

Have to be careful, because using JOINs risks duplicated data for the sake of the unique supporting data. I re-wrote your query as:
UPDATE QUOTES
SET status_id = 1
WHERE id NOT IN (SELECT cr.record_id
FROM COLLECTION_RECORDS cr
WHERE cr.type = 'Quote')
AND id NOT IN (SELECT sr.record_id
FROM SUBCOLLECTION_RECORDS sr
WHERE sr.type = 'Quote')
Using LEFT JOIN/IS NULL:
UPDATE QUOTES
LEFT JOIN COLLECTION_RECORDS cr ON cr.record_id = id
AND cr.type = 'Quote'
LEFT JOIN SUBCOLLECTION_RECORDS sr ON sr.record_id = id
AND sr.type = 'Quote'
SET status_id = 1
WHERE cr.record_id IS NULL
AND sr.record_id IS NULL

My guess is that it's mainly due to the <> (NOT EQUALS) operator. Is that really what you're looking for here?

Also, if you have a Quote record in both the joinging tables....you will get 2 records back. Seems that taking one of the joins out returns only one record to you. Try doing a select instead of the update on a certain Quote that exists in both tables and see if you get two records back. You will have to modify the joins down in order to get one quote record returned.

Related

UPDATE SET = SELECT FROM

I am trying to update table based on a select query using this:
UPDATE branches SET name =
(SELECT CONCAT(comp.name," ",bra.subsurb) as newname
FROM companies comp
RIGHT JOIN branches bra
ON comp.id = bra.company_id)
Which, according to this question, should work
but this produces an error: You can't specify target table 'branches' for update in FROM clause
Not sure what I am doing wrong.
EDIT:
Eventually this query did what I'm after:
UPDATE branches bra LEFT JOIN companies comp
ON comp.id = bra.company_id
SET bra.name = CONCAT(comp.name," ",bra.subsurb)
The error itself is pretty self explanatory, you are selecting from the table you are updating. Instead, you can use JOIN in the update statement. Try this:
UPDATE branches b
LEFT JOIN companies c ON c.id = b.company_id
SET b.name = CONCAT(c.name, " ", b.subsurb);
Note that because you're using a left join here to select all branches, regardless of whether or not they have a company, you may get null values for some names, so be careful about that.
In MySQL, you can't modify the same table which you use in the SELECT part.
This behaviour is documented at: http://dev.mysql.com/doc/refman/5.6/en/update.html
You will need to stop using the nested subquery and execute the operation in two parts, or alternatively use a simple where clause.
For more information please go through the following link
MySQL Error 1093 - Can't specify target table for update in FROM clause
The error you are getting is a restriction in MySQL.
To approach this problem, first write a SELECT statement that returns both the existing column value, and the new value you want to assign to the column:
e.g.
SELECT b.company_id
, b.name AS old_name
, CONCAT(c.name,' ',b.subsurb) AS new_name
FROM branches b
LEFT
JOIN companies c
ON c.id = b.company_id
NOTE: beware of NULL values returned for c.name (possible because of the outer join). CONCAT including a NULL may return NULL.
Once that is returning the rows you want to update, convert that to an UPDATE by replacing the SELECT ... FROM with the keyword UPDATE, and add a SET clause immediately before the WHERE clause:
UPDATE branches b
LEFT
JOIN companies c
ON c.id = b.company_id
SET b.name = CONCAT(c.name,' ',b.subsurb)

retrieve only records that has join records

I have following sql query, which retrieves me joined records. However I want to get places which doesnt have joined records, see below:
SELECT `places`.* FROM `places` INNER JOIN `quotes` ON `places`.`id` = `quotes`.`place_id`
WHERE `quotes`.`user_id` = 1 AND
Here comes part I don't know how to write, but I want only to get places where count of quotes = 0 like:
"quotes.count == 0"
How to add another clause to this sql query, to match my requests?
You want an outer join, presumably a left outer join:
SELECT `places`.*
FROM `places` LEFT JOIN
`quotes`
ON `places`.`id` = `quotes`.`place_id` AND
`quotes`.`user_id` = 1
WHERE quotes.place_id is null;
Note that the condition in the where clause has been moved to the on clause. When there is no match, the columns from quotes are filled with NULLs -- which would cause a where condition to fail.

Need mysql query to pull data from two tables

So after helpful feedback from my original question, I now have this query:
SELECT sessions.id, sessions.title, sessions.abstract, sessions.presenters, sessions.proposal_id, proposals.outcomes, proposals.CategorySelection, proposals.research3, proposals.research4, proposals.research5, proposals.research6, proposals.innovation3, proposals.innovation4, proposals.innovation5,proposals.innovation6, proposals.application3, proposals.application4, proposals.application5, proposals.application6, proposals.integration3, proposals.integration4, proposals.integration5, proposals.integration6, proposals.references, proposals.organization
FROM sessions, proposals
INNER JOIN proposals ON proposals.id = sessions.proposal_id
WHERE sessions.id = '$id
LIMIT 1;)
that is getting me nowhere fast. What am I doing wrong?
Original question:
I need to pull several fields from one table and several more from a second table. The criteria is that a field called proposal_id match the id field of the second table. I am fairly new so this is what I have so far. It is not working, but not sure how to make it work.
(SELECT `title`,`abstract`,`presenters`,`proposal_id` FROM `sessions` WHERE `id`='$id')
UNION
(SELECT `outcomes`,`CategorySelection`,`research3`,`research4`,`research5`,`research6`,`innovation3`,`innovation4`,`innovation5`,
`innovation6`,`application3`,`application4`,`application5`,`application6`,`integration3`,`integration4`,`integration5`,`integration6`,`references`,`organization` FROM `proposals` WHERE `id`= `sessions`.`proposal_id`)
LIMIT 1;
You need to use JOIN not UNION
select
s.*,p.*
from `sessions` s
inner join `proposals` p on p.id = s.proposal_id
where s.id = '$id'
This is how you can join both the tables using the common key between.
You can select the specific fields instead of .* by specifying the column names as
s.col1,s.col2,p.col1,p.col2
etc
Try to use JOINS, where you can match the related fields from both the tables , this is the most convenient way to fetch records from multiple tables
UNION is used when you want to combine two queries
select a.id,b.some_field from table1 as a
INNER JOIN table2 as b ON b.prospal_id = a.id

MySQL UPDATE with SELECT (mark "item" as read)

I have the following query which selects personal messages (PM) from "ac_pms" table. Additional info is fetching from other table - "ac_accounts" using LEFT JOIN. There is "pm_read" column in "ac_pms" table which define a PM is read or not. I need to set that field (pm_read) to "1" while selecting PMs.
SELECT p.*, a.seller_id, a.winner_id
FROM `ac_pms` AS p
LEFT JOIN `ac_accounts` AS a ON p.pm_for_lot = a.id
WHERE (p.pm_from=[user_id] OR p.pm_to=[user_id])
AND p.pm_for_lot=[account_id]
ORDER BY p.pm_date DESC;
I cannot imagine where to insert UPDATE expression to SET pm_read = 1.
You can't SELECT with UPDATE in the same SQL statement.
However, you can UPDATE with JOIN like this:
UPDATE ac_pms AS p
LEFT JOIN ac_accounts AS a ON p.pm_for_lot = a.id
SET p.pm_read = 1
WHERE (p.pm_from=[user_id] OR p.pm_to=[user_id])
AND p.pm_for_lot = [account_id];
Then you can make another SELECT after that.

UPDATE affecting less rows than equivalent SELECT

The following query returns 2303 rows:
SELECT a.*
FROM cur_analises a
INNER JOIN cur_materias_subsidiarias ms
ON ms.materia_id = a.materia_id
AND ms.subsidiaria_id IN(SELECT id FROM cur_subsidiarias WHERE cliente_id = 134)
INNER JOIN cur_materias m
ON m.id = a.materia_id
INNER JOIN cur_clientes c
ON c.carga_id = ms.subsidiaria_id
WHERE a.cliente_id = 134;
I need to update the cliente_id field of all those 2303 rows from table cur_analises with the value from cur_clientes.id. However, when I try to turn that SELECT query into the following UPDATE, it only affects 2297 rows, according to MySQL Workbench:
UPDATE cur_analises a
INNER JOIN cur_materias_subsidiarias ms
ON ms.materia_id = a.materia_id
AND ms.subsidiaria_id IN(SELECT id FROM cur_subsidiarias WHERE cliente_id = 134)
INNER JOIN cur_materias m
ON m.id = a.materia_id
INNER JOIN cur_clientes c
ON c.carga_id = ms.subsidiaria_id
SET a.cliente_id = c.id
WHERE a.cliente_id = 134;
I have no idea why it's missing 6 rows. What am I doing wrong?
You are probably not joining on a unique value or set of values at some point in the query causing denormalization of your result set. Then when you do the update it only updates the rows that actually meet the criteria of the joins for the table aliased as a. Only you can know what are truly non denormalizing joins in your query and fix them.
We had a similar case, the issue was with mysql partitioning. Once we revert partitioning everything is ok again.