I have a table that has been functional and i added a column to the table. After adding the column i want to add the result of a query (query is same for all but different results) into that column all at once instead of one at a time which will be time consuming. How can i achieve that? Cos after updating, i have just one result in all the column, i cannot use a where clause cos it will require me doing it one after the other
$stmt = $pdo->prepare("UPDATE table SET my_value = '$myValue' ");
$stmt->execute();
UPDATE table
SET my_value = (select col from some_table where ...)
If the value is the same for all rows, I would advise using cross join:
update table t cross join
(select newval . . .) x
set t.col = x.newval;
Note: this is better than a subquery, because the subquery is guaranteed to be evaluated only once.
If you are trying to say that the value is the same for groups of columns, then extend this to a join:
update table t join
(select grp, newval . . .) x
on t.grp = x.grp
set t.col = x.newval;
After adding the column I want to add the result of a query (query
result is same for all) into that column all at once instead of one at
a time which will be time consuming.
The solution depends on what you mean by "Is the same for all the rows."
If you have one value that is exactly the same for all columns, you can just ask for it and then update. This is usually faster (and allows you to debug more easily) than using pure SQL to achieve everything.
If, on the other hand, you mean the values of that column are retrieved by the same query, but will be different for different rows, then a subquery or a cross join as Gordon suggested will do the trick.
Related
Table has approximately 100 000 records(tuples). Without where clause it takes only few miliseconds whereas takes 4-5 secs when use where clause.
SELECT COUNT(DISTINCT id) FROM tablename WHERE shippable = '1'
I also tried this one but it takes more time as compared to previous one.
SELECT count(rowsss) FROM (SELECT count(*) as rowsss FROM tablename WHERE shippable = '1' GROUP BY id) as T
This is the output when I use EXPLAIN keyword before starting of mysql query
If you a need a filter you could use an index on shippable eg:
create index shippable_ixd on tablename (shippable);
in this way the scan for the table is limited to values that match
and avoid the scan for entire table
and based on the fact you also need the column id you could also trying alternatively a composite index
create index shippable_ixd on tablename (shippable, id);
the sqloptimizer should retrive directly form the index the info needed.
In this case The use of composite index ( with a redundant id not need by where clause) is useful because the SQL engine retrive all the data needed to the query just scanning the index, avoiding the access to the data in the table. This tecnique is use frequently for db queries tuning.
When you checking any condition that time both value should be in same type then execution of query will be fast.
SELECT count(rowsss) FROM (SELECT count(*) as rowsss FROM tablename WHERE CAST(shippable AS CHAR) = '1' GROUP BY id) as T
I'm restructuring some code, this is a PHP - MYSQL project. So i'm trying to update some tables in a single query or at least two.
Is this possible to achieve without Joins? What is the best choice ?
UPDATE document D SET D.status = 2,
CASE
WHEN D.type 'A' THEN (UPDATE table_1 SET active = 1 WHERE id_table1 = D.id_document)
WHEN D.type 'B' THEN (UPDATE table_2 SET active = 1 WHERE id_table2 = D.id_document)
WHEN D.type 'C' THEN (UPDATE table_3 SET active = 1 WHERE id_table3 = D.id_document)
END
WHERE D.id_document = %s
I don't mind to separate the first table " document D ", but I need the " case when " to update multiple tables in a single query because they are like 11 tables.
Are you trying to put it all in one query to improve performance? That won't help in this case, since it will take the same amount of time as it would if each subquery were executed separately.
You would get much cleaner code and better performance if you determined the table name in your php code and then passed that onto a much simpler query string.
Not to leave the question unanswered. Based on what I researched.
No, you can not do an "update" in a subquery.
No, you can not use the "case" like that.
The only thing that can be done is:
Use joins to update multiple tables
UPDATE table_1
INNER JOIN table_2 ON table_1.id = table_2.id
INNER JOIN table_3 ON table_3.id = table_3.id
SET table_1.column = '', table_2.column = ''
WHERE any condition;
And the "case" can only be used in a single way
UPDATE table SET
column = CASE columX WHEN 'A' THEN '2' ELSE column END,
column2 = CASE columX WHEN 'B' THEN '2' ELSE column2 END
Combining the two, I was able to achieve what I needed.
Remember that you can make different types of join and play with the "where". In the "case" clause, updating the column is mandatory, not optional, so I use the same column in "else" to leave it with the default value when I do not need to update that column.
I'm a bit confused about DISTINCT keyword. Let's guess that this query will get all the records distincting the columns set in the query:
$query = "SELECT DISTINCT name FROM people";
Now, that query is fetching all the records distincting column "name" and at the same time only fetching "name" column. How I'm supposed to ONLY distinct one column and at the same time get all the desired columns?
This would be the scheme:
NEEDED COLUMNS
name
surname
age
DISTINCTING COLUMNS
name
What would be the correct sintaxis for that query? Thanks in advance.
If you want one row per name, then a normal method is an aggregation query:
select name, max(surname) as surname, max(age) as age
from t
group by name;
MySQL supports an extension of the group by, which allows you to write a query such as:
select t.*
from t
group by name;
I strongly recommend that you do not use this. It is non-standard and the values come from indeterminate matching rows. There is not even a guarantee that they come from the same row (although they typically do in practice).
Often, you want something like that biggest age. If so, you handle this differently:
select t.*
from t
where t.age = (select max(t2.age) from t t2 where t2.name = t.name);
Note: This doesn't use group by. And, it will return duplicates if there are multiple rows with the same age.
Another method uses variables -- another MySQL-specific feature. But, if you are still learning about select, you should probably wait to learn about variables.
I have 2 tables with similar columns in MYSQL. I am copying data from one to another with INSERT INTO table2 SELECT * FROM table1 WHERE column1=smth. I have different columns as autoincrement and KEY in tables. When I use mysqli_insert_id i get the first one rather then last one inserted. Is there any way to get the last one?
Thanks
There is no inherit ordering of data in a relational database. You have to specify which field it is that you wish to order by like:
INSERT INTO table2
SELECT *
FROM table1
WHERE column1=smth
ORDER BY <field to sort by here>
LIMIT 1;
Relying on the order a record is written to a table is a very bad idea. If you have an auto-numbered id on table1 then just use ORDER BY id DESC LIMIT 1 to sort the result set by ID in descending order and pick the last one.
Updated to address OP's question about mysqli_insert_id
According to the Mysql reference the function called here is last_insert_id() where it states:
Important If you insert multiple rows using a single INSERT statement,
LAST_INSERT_ID() returns the value generated for the first inserted
row only. The reason for this is to make it possible to reproduce
easily the same INSERT statement against some other server.
Unfortunately, you'll have to do a second query to get the true "Last inserted id". Your best bet might be to run a SELECT COUNT(*) FROM table1 WHERE column1=smth; and then use that count(*) return to add to the mysqli_insert_id value. That's not great, but if you have high volume where this one function is getting hit a lot, this is probably the safest route.
The less safe route would be SELECT max(id) FROM table2 or SELECT max(id) FROM table2 Where column1=smth. But... again, depending on your keys and the number of times this insert is getting hit, this might be risky.
I have tried to set the max value for the particular column but that is not working for me. I do not know where i'm going wrong.
UPDATE `upload_video`
SET order_id ='select max(order_id)+1
FROM upload_video'
WHERE `video_id` = 22
This is my query i run the select max(order_id)+1 from upload_video query separately which is giving the result. But if i use this query in update query, the query is executing without error. But the order_id is not updating properly. please help me
Your query is almost correct in standard SQL, you only need to use brackets () instead of apostrophe ':
SET order_id = (SELECT MAX(...) ...)
but MySQL doesn't allow you to update a table while selecting from the same table, a workaround is to use a subquery that calculates the value that you need, and to join your subquery with the table you need to update:
UPDATE
upload_video JOIN (SELECT COALESCE(MAX(order_id),0)+1 max_id
FROM upload_video) s
SET
upload_video.order_id=s.max_id
WHERE
video_id=22
Please see fiddle here.
You have a typo in the statement, you used UPADTE instead of UPDATE.
One problem is, don't quote the subquery. You have used single quotes, which means the expression select max(order_id)+1... was interpreted as a text literal (a varchar). But you clearly don't want that (I guess order_id is a number). What you want instead is to evaluate the subquery. However, if you try:
UPDATE `upload_video`
SET order_id =(select max(order_id)+1
FROM upload_video)
WHERE `video_id` = 22
then MySQL doesn't allow it (I didn't know about that). Other databases such as PostgreSQL allow it. So you might need two statements:
select #id = coalesce(max(order_id), 0) + 1 FROM upload_video;
UPDATE `upload_video` SET order_id = #id WHERE `video_id` = 22;
Please note this works in MySQL but not in other databases.
Try this:
UPDATE `upload_video`
SET order_id =(select COALESCE(max(U2.order_id),0)+1
FROM upload_video U2)
WHERE `video_id` = 22
Peraphs this query goes in error because MySql doesn't want to use the same table in UPDATE and in subquery.
If your case please write two queries.
The first get the maximum value, the second does update