This is what i am doing
update t1 set x=a,y=b where a and b are obtained from (select query here)
I know the select query
The select query returns multiple results which are the same
When I use group by or distinct query execution slows down considerably
a and b are forward references so mysql reports an error
I want to set a equal to the value obtained in the first row and b equal to the value obtained in the first row for the respective columns, to avoid group by. I don't know how to refer to the first result from the select query.
How can i achieve all this?
LIMIT specifies the number of rows to return from the beginning of the result set:
SELECT * FROM t2 LIMIT 1; # Retrieve 1st row
LIMIT in your case is applied in the subquery in your from clause.
These linsk can help you out with update that uses a subquery:
Update with Subquery
Subqueries in MySQL, Part 1
you might be looking for something like...
update T1, (select Sub1.a, Sub1.b from YourSubQueryTable Sub1 where ... ) SubResult
set T1.a = SubResult.a,
T1.b = SubResult.b
where
Some T1.Criteria To be applied
Related
I am trying to update a column in the following table 'jobqueue' using the results from a SELECT query performed on the 'mdtinfo' table.
The column I am trying to update is called ignore and I need to set the value to 1 from its default of 0.
update jobqueue
set jobqueue.`ignore`= '1'
where (SELECT JobQueue_job_queue_id
FROM mdtinfo
WHERE product_name = 'Example')
The above query returns the following error: SQL Error (1242): Subquery returns more than 1 row.
When running the select query on it's own it returns results successfully.
In MySQL, a value of zero appearing in a WHERE clause means false.
So, UPDATE something SET col=val WHERE (SELECT colx FROM sometable) has the potential to be a valid query. If the inner SELECT gets just one row, and its colx column has the value 0, the update won't do anything. If the colx column has a nonzero value the query means UPDATE something SET col=val WHERE true. Accordingly, every row in sometable will be updated. I doubt that's what you want.
If the inner SELECT happens to return more than one row, the query isn't valid. You'll get the error 1242 you actually received.
(This business of interpreting numbers as Boolean values causes MySQL to accept some otherwise dodgy query syntax, like the syntax in your question.)
I guess you want to retrieve the job_queue_id values for the row or rows you actually want to update. So try something like this.
update jobqueue
set jobqueue.`ignore`= '1'
where jobqueue.job_queue_id IN (SELECT JobQueue_job_queue_id
FROM mdtinfo
WHERE product_name = 'Example')
I guessed you have a column jobqueue.job_queue_id. You didn't tell us what columns you have in jobqueue.
update jobqueue
set jobqueue.`ignore`= '1'
where jobqueue.`job_queue_id` IN (SELECT GROUP_CONCAT(JobQueue_job_queue_id)
FROM mdtinfo
WHERE product_name = 'Example' GROUP BY product_name)
you should write column name in where condition.
I was wondering if there's any way to add a subquery with a switch case to the form clause of my select query in order to select a table based on a condition.
For example:
select a.*
from (select (case when (table2.column = 'something')
then (table2.tablename1)
else (table2.tablename2)) as tablename
from table2
where table2.column2 = 'blabla'
limit 1
) a
I tried to write that in many variation & so far non of them worked.
On the most successful tryouts (when I got no mysql errors) it returned the name of the table as the result itself (for example: the value that's in table2.tablename2). I understand why it did that (because I selected everything from a select results...) but how can I use the tablename from the results in order to set the table on the main query?
Hope that make sense...
Any idea?
I've got a query that is returning a set of rows. I want to LIMIT what actually gets returned to some subset of these rows by range, relative either to the beginning or end of the range. I can do this easily if the range is only relative to the beginning. For instance, if I want to return rows 5-7 I can do:
SELECT * FROM <table> WHERE <condition> ORDER BY rowid ASC LIMIT 5,2
The only translation I need to do is from (index0,index1) to offset,length where offset=index0 and length=index1-index0.
But I also am trying to allow the range to be specified relative to the end of the range in a single query, i.e. without running a query first to determine the number of rows and then a second query based on this information. So for example if I specify a row range of (-5,-1) this means that I want the last five rows returned. I cannot pass a negative value to LIMIT.
In reading similar questions, one proposed solution seemed to be to change the ORDER of the query. So I suppose I could do:
SELECT * FROM <table> WHERE <condition> ORDER BY rowid DESC LIMIT 1,5
Now I have two problems. First, the returned set is in the wrong order, I still want it return in ascending order. So now I have to have a subquery to reorder everything:
SELECT * FROM (SELECT * FROM <table> WHERE <condition> ORDER BY rowid DESC LIMIT 1,5) AS x ORDER BY x.rowid ASC;
I'm not sure if there is a better way to do it than that, but there is a second issue: this does not work if the starting and ending part of the range are mixed as to what they are relative to. Suppose I want to return the range (10,-2) which is all rows from the tenth to the next to last. In this case, neither of the above approaches will work.
I also saw where the function mysql_num_rows() was mentioned although it did not give example SQL of how to use it.
SELECT * FROM <table> WHERE <condition> ORDER BY rowid DESC LIMIT 10,mysql_num_rows()-2;
But when I try to run this query, I get this error:
ERROR 1327 (42000): Undeclared variable: mysql_num_rows
What about reversing your approach? Asking for rows in range (10, -2) means "everything except first nine rows and last one".
You can translate it into
select * from yourTable order by rowid asc
minus
select * fom yourTable order by rowid asc limit 9
minus
select * fom yourTable order by rowid desc limit 1
Edit
Since MySQL does not support MINUS, the query above could be rewritten using left join instead
select t1.*
from yourTable t1
left join
(select rowid fom yourTable order by rowid asc limit 9) t2
on t1.rowid = t2.rowid
left join
(select rowid fom yourTable order by rowid desc limit 1) t3
on t1.rowid = t3.id
where t2.rowid is null and t3.rowid is null
order by t1.rowid asc
This is based on a different answer that was given to this question, which used MINUS. Unfortunately, MySQL does not support this operator. I used NOT IN instead, and furthermore I had to wrap my query inside additional queries to avoid the MySQL issue of lack of support for LIMIT being in an IN sub-query.
So the premise of the solution as provided by the other answer is to treat a positive starting index and a negative ending indexes as a different case from both indicies negative or positive. Then, select everything but exclude the range at the start and finish. The actual code that MySQL likes and which works for the example range of (10,-2) is:
SELECT *
FROM <table>
WHERE <conditions>
AND rowid NOT IN
(
SELECT * FROM (
SELECT rowid FROM <table> WHERE <conditions> ORDER BY rowid ASC LIMIT 9
)
)
AND rowid NOT IN
(
SELECT * FROM (
SELECT rowid FROM <table> WHERE <conditions> ORDER BY rowid DESC LIMIT 1
)
)
Or more generally, for the range (i0,i1) where i0>=0 and i1<0, replace 9 with i0-1 and 1 with -i1-1. Of course, if either of these values are less than one, that portion of the query can be excluded.
I have a question on HAVING statement in SQL.
Is a query like this possible?
SELECT COUNT(T.IDtif) AS NumeroTifosi
FROM Tifosi T, Partita P
WHERE T.IDtif=P.Tifoso AND P.Partita=P.Idpar
HAVING COUNT(P.Idpar) = ( SELECT COUNT(Idpar) FROM Partita
WHERE Data BETWEEN “2002101” AND ”20021231”)
I don't understand if it is possible to compare an aggregation function, in a HAVING statement, with a subquery that returns a single value.
That's what the parentheses do. You can compare a single result of a SELECT by turning telling SQL "it's ok, this has one value".
It could be:
SELECT ColA = (SELECT ColB from TableB Where Id = 1)
FROM TableA
or
SELECT *
FROM TableA
WHERE ColA = (SELECT ColB from TableB Where Id = 1)
or even with HAVING as you describe.
Yes. This query if perfectly valid. Are you getting an error when you try to run it?
What you are doing is running a subquery once to return a count. Then for each group, you are checking if the number of rows in that group is equal to the number returned by the subquery.
This query returns 0 elements:
SELECT `table1`.`id` FROM `table1`,`table2` WHERE `table1`.`id`='222' ;
However I expect to have a result because this query returns one element:
SELECT `table1`.`id` FROM `table1` WHERE `table1`.`id`='222' ;
Is there a MySQL parameter to set in order to get a result with the first query where table2 is not used?
In the first query you used 2 table but in the second query you used one table.Because of this the result is different.
If you not specify join explicitly also it will use Cartesian product