简体   繁体   中英

Combine multiple select with update

I have a query that is dragging down my application. There has to be a way to improve this by joining the update with the selects. Any help appreciated. Here is the very slow query:

Select t1.id, t2.tracker from Table1 t1, Table2 t2 where t1.id=t2.id and t2.tracker is not null

The above returns a row set I can process. For each row that is returned, I check tracker in a third table to see if only 1 row exists:

select tracker from Table3 where tracker="from above query". 

If tracker has a count of 1 row in Table 3, I then perform an update on Table 1.

Update Table 1, set some field where id=t1.id

How do I combine this? The answer listed is wonderful, but I guess the question wasn't made clear enough. Therefore, I have edited the question.

Table 1 returns the possible list of ID's to update. Table 2 returns the tracker I need to search Table 3. Table 3 tells me if the tracker exists only once, so I can use this to go back to Table 1 and update it.

By using a HAVING clause and an additional LEFT JOIN , you can combine the first two queries into one returning the tracker only for those with one record in Table3 with an expression like HAVING COUNT(t3.tracker) = 1

The SELECT portion then looks like:

SELECT
  t1.id,
  t2.tracker
FROM 
  -- Your original comma-separated FROM clause (implicit inner join)
  -- has been replaced with a more modern explicit INNER JOIN, which
  -- works more clearly with the LEFT JOIN we need to do.
  Table1 t1
  INNER JOIN Table2 t2 ON t1.id = t2.id
  -- left join table 3 by tracker value
  LEFT JOIN Table3 t3 ON t2.tracker = t3.tracker
WHERE t2.tracker IS NOT NULL
GROUP BY
  t1.id,
  t2.tracker
-- limit the group to only those with 1 tracker in t3
HAVING COUNT(t3.tracker) = 1

Now, you should be able to stuff that into an UPDATE query with a JOIN . MySQL's update-join syntax would look like:

UPDATE 
  Table1 t_up
  -- join Table1 in its normal form against the query from above
  -- MySQL won't allow an IN () subquery for update in most versions
  -- so it has to be done as a join instead.
  JOIN (
    -- the subquery only needs to return t1.id
    SELECT t1.id
    FROM 
      Table1 t1
      INNER JOIN Table2 t2 ON t1.id = t2.id
      LEFT JOIN Table3 t3 ON t2.tracker = t3.tracker
    -- Filter to those with non-null t2.tracker
    WHERE t2.tracker IS NOT NULL
    GROUP BY
      -- Since only id was in SELECT, only id needs to be in GROUP BY
      t1.id
    HAVING COUNT(t3.tracker) = 1
  ) t_set ON t_up.id = t_set.id
SET t_up.some_field = 'SOME NEW VALUE'

Here is a demonstration of the concept in action...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM