MySQL: save SELECT to variable - mysql

I have something like this:
SELECT FROM table
WHERE field NOT IN (
SELECT FROM other_table ... //SECOND QUERY
)
Problem: I don't want SECOND QUERY be executed for each row of table. Can I save QUERY 2 result to some variable?

You can check if the query will run for every row by running EXPLAIN and looking if it its a DEPENDENT SUBQUERY or SUBQUERY. Dependent will run for each row.
Based on that you want to 'save it to a variable' I'm guessing it will not be dependent.
If you want to save a resultset to a 'variable' you need to use a temp table. In this case it will not be necessary.

A LEFT NULL JOIN may be a lot faster for you.
SELECT *
FROM table AS t
LEFT JOIN other_table AS ot ON ot.field = t.field
WHERE ot.field IS NULL

Related

Optimize performance of MySQL UPDATE query containing EXISTS

Can anybody please give me a hint on how to optimize this update MySQL query that takes about a minute to process?
UPDATE store s
SET reservation=1
WHERE EXISTS (
SELECT 1
FROM item i
WHERE s.reservation=0
AND s.status!=9
AND s.id=i.store_id
AND i.store_id!=0
)
I need to update (set reservation=1) all rows in "store" table (which is very large) where there is currently reservation=0 but it's id exists in another table "item". Table "item" is also large but not as much as "store".
I'am not an expert on creating efficient queries so forgive me if this is just a completely wrong attitude and the whole thing has a simple solution.
Thanks for any ideas.
It looks like some of the predicates in the correlated subquery could be moved to the outer query. For example, I believe this is equivalent:
UPDATE store s
SET s.reservation = 1
WHERE s.reservation = 0
AND s.status != 9
AND s.id != 0
AND EXISTS ( SELECT 1
FROM item i
WHERE i.store_id = s.id
)
For best performance of that, at a minimum, we'd want an index on store that has reservation as the leading column. Also including the status and id columns would mean those conditions could be checked from the index page, without a lookup of the underlying page in the table.
And for that correlated subquery (dependent query), we'd want an index on item with a store_id as the leading column.
As another option, consider re-writing the correlated subquery as a JOIN operation, for example:
UPDATE store s
JOIN item i
ON i.store_id = s.id
SET s.reservation = 1
WHERE s.reservation = 0
AND s.status != 9
AND s.id != 0
If you're running MySQL 5.5 or earlier, you can't get an EXPLAIN on an UPDATE statement. The closest we can get is rewriting the query as a SELECT, and getting an EXPLAIN on that. MySQL 5.6 does support EXPLAIN on an UPDATE statement.
You can try to use:
UPDATE store s INNER JOIN item i ON s.id=i.store_id SET reservation=1 WHERE i.store_id!=0 AND s.reservation=0 AND s.status != 9;
This case should works faster because you will not go thru all 'item' table each time when you need to check 'store' row.

Nested SELECT SQL Queries Workbench

Hi i have this query but its giving me an error of Operand should contain 1 column(s) not sure why?
Select *,
(Select *
FROM InstrumentModel
WHERE InstrumentModel.InstrumentModelID=Instrument.InstrumentModelID)
FROM Instrument
according to your query you wanted to get data from instrument and instrumentModel table and in your case its expecting "from table name " after your select * .when the subselect query runs to get its result its not finding table instrument.InstrumentModelId inorder to fetch result from both the table by matching you can use join .or you can also select perticuler fields by tableName.fieldName and in where condition use your condition.
like :
select Instrument.x,InstrumentModel.y
from instrument,instrumentModel
where instrument.x=instrumentModel.y
You can use a join to select from 2 connected tables
select *
from Instrument i
join InstrumentModel m on m.InstrumentModelID = i.InstrumentModelID
When you use subqueries in the column list, they need to return exactly one value. You can read more in the documentation
as a user commented in the documentation, using subqueries like this can ruin your performance:
when the same subquery is used several times, mysql does not use this fact to optimize the query, so be careful not to run into performance problems.
example:
SELECT
col0,
(SELECT col1 FROM table1 WHERE table1.id = table0.id),
(SELECT col2 FROM table1 WHERE table1.id = table0.id)
FROM
table0
WHERE ...
the join of table0 with table1 is executed once for EACH subquery, leading to very bad performance for this kind of query.
Therefore you should rather join the tables, as described by the other answer.

How to optimize a MySQL update which contains an "in" subquery?

How do I optimize the following update because the sub-query is being executed for each row in table a?
update
a
set
col = 1
where
col_foreign_id not in (select col_foreign_id in b)
You could potentially use an outer join where there are no matching records instead of your not in:
update table1 a
left join table2 b on a.col_foreign_id = b.col_foreign_id
set a.col = 1
where b.col_foreign_id is null
This should use a simple select type rather than a dependent subquery.
Your current query (or the one that actually works since the example in the OP doesn't look like it would) is potentially dangerous in that a NULL in b.col_foreign_id would cause nothing to match, and you'd update no rows.
not exists would also be something to look at if you want to replace not in.
I can't tell you that this will make your query any faster, but there is some good info here. You'll have to test in your environment.
Here's a SQL Fiddle illuminating the differences between in, exists, and outer join (check the rows returned, null handling, and execution plans).

How to merge this two query statement into one query statement

1. SELECT * FROM instalmentsdetails WHERE instalmentName='Third Installment'AND studentFeeId='1'
2. select max(`receiptNo`)as `receiptNo` FROM instalmentsdetails
Table instalmentsdetails
instalmentsDetailsId
studentFeeId
receiptNo
instalmentName
amount
dueDate
fineAmt
waivedAmt
scholarShip
grandTotal
status
Little confused .How to merge this two query statement into one query statement
P.S: One statement checks for the condition and the other checks for the max of receiptNo in that table
I want both the values in one query
Is this what you want?
SELECT max(`receiptNo`) as `receiptNo`
FROM instalmentsdetails
WHERE instalmentName='Third Installment' AND studentFeeId='1'
Update: how about this:
SELECT *
FROM instalmentsdetails as inds
INNER JOIN (
SELECT max(`receiptNo`) as `maxreceiptNo`
FROM instalmentsdetails
) as maxt
WHERE inds.instalmentName='Third Installment' AND inds.studentFeeId='1'
This applies the filter to the table, then adds an extra column (the maximum receiptNo)
Assuming the goal is to get:
a list of instalmentsdetails with specific a instalmentName and studentFeeId
global maximum
 
SELECT *, 0 AS receiptNo FROM instalmentsdetails WHERE instalmentName='Third Installment'AND studentFeeId='1'
UNION
select *, max(`receiptNo`) as `receiptNo` FROM instalmentsdetails
Update
Apparently the OP simply wants to consolidate separate query results into a single row. In that case:
SELECT
*,
(SELECT max(`receiptNo`) FROM instalmentsdetails) AS maxReceiptNo
FROM instalmentsdetails WHERE instalmentName='Third Installment'AND studentFeeId='1'
From all the reading, Matt is correct, but maybe I can help explain what he's doing...
The first part of the query (From InstalmentsDetails WHERE YourCondition) will get all records that qualify for the condition.
THEN, by doing a JOIN to the second query (select max( 'receiptNo' ) from... with no where clause ) will ALWAYS return a single row, single column of the maximum receipt without regard to ANY criteria.
This creates an implied Cartesian result. Join everything in the first table with every record in the second. Since there is no explicit join condition, every row will get the same "max()" value as a returned column. And since there will only be one record in the select max() call, you never worry about duplicates.
Now, if you wanted the maximum receipt within the same criteria, you would just copy that same criteria to the select max() query portion.

Loops in MySQL alone

I'd like to select from one table and use the results of that select to update another table, but only based on certain conditions. Is this possible with a 1-time SQL query?
Yes it is.
UPDATE
tableToUpdate AS ttu
[LEFT|RIGHT|INNER] JOIN
otherTable AS ot
ON
joinCondition
SET
ttu.field = ot.field
WHERE
conditionsToBeMet
AS otherTable you can just use the SELECT query that you use to fetch your resultset.