Updating several records in a database with increasing value - php

I need to update several records in a table, and am hoping to accomplish it in one query.
I have a php array of id's for a few of the records in my table. The array is in a specific order, and I need to update a value for each id with the position/key that the id is in the array. I could easily loop through each value in the array and run a query for each record that needs to be updated, but I am looking for a way to possibly update each record in one query.
The following will give me the desired result, but I am looking for a one query solution.
$ID = array('3','2','6','5','9');
for($i = 0; $i <= 4; $i++){
$q = "UPDATE table SET blah = ".$i." WHERE id = ".$ID[$i];
mysql_query($q) or die();
}
Thanks.

2 queries:
First only needed in case you have used #var already.
SET #var := -1;
And then (note FIND_IN_SET wants a comma-separated string):
UPDATE tablename
SET blah = #var := #var +1
WHERE id IN (3,2,6,5,9)
ORDER BY FIND_IN_SET(id,'3,2,6,5,9');
If you have an array with key=>postition pairs, this could be used:
$array = array(2 => 40,3 => 12,5 => 8,6 => 9,9 =>13129);
mysql_query("
UPDATE bla
SET blah = ELT(
FIELD(id,".implode(',',array_keys($array))."),
".implode(',',$array).")
WHERE id IN (".implode(',',array_keys($array)).")");

A big long ugly if or case statement would do the trick:
UPDATE ...
SET blah = IF(id=3,1,IF(id=2, 2, IF(id=6,3, IF....))))
WHERE id IN (3,2,6,....)
it'd quickly become unmanageable, but it would accomplish things in a single query. A slightly cleaner, more portable alternative:
UPDATE
SET blah = CASE id WHEN 3 THEN 1 WHEN 2 THEN 2 WHEN 6 THEN 3 .... END CASE
WHERE id in (3,2,6,...)

Try this:
INSERT INTO tbl_name (idCol, valCol) VALUES (id1, value1),(id2, value2)
ON DUPLICATE KEY UPDATE
idCol = VALUE(idCol),
valCol = VALUE(valCol)
You could also use a stored procedure, passing it a string of the ID's:
CREATE PROCEDURE updateItems( firstNum INT NOT NULL, ids TEXT NOT NULL) BEGIN
#id := ... # Some expression to get the first ID.
WHILE id != "" DO
SET ids := ... # Some expression to get the rest of the string.
UPDATE table SET blah = firstNum WHERE id = #id;
SET firstNum = firstNum +1;
#id := ... ;
END;
END $$
Also, there was one trick with LAST_INSERT_ID() - if you call it with a param, like LAST_INSERT_ID( 123 ), successive call to LAST_INSERT_ID() will give you 123.
Could be used together with #variables to achieve that goal.
You might get some inspiration here: http://ondra.zizka.cz/stranky/programovani/sql/mysql_stored_procedures.texy

It's impossible in this way ...Well, it's possible but I'd suggest you not to do it, 5 queries aren't horrors

$q = "UPDATE table SET blah = ".$i." WHERE id in ('3','2','6','5','9')";

If you are concerned about performance, you should take a look at using prepared statements and transactions.
There is most likely a solution to doing this in one single query, but it would most likely get really messy.

your better of using foreach then you don't have to set a $i limit.
i think its quick to do it this way
$id = array('3','2','6','5','9');
$i=0;
foreach ($id as $v){
$q = "UPDATE table SET blah = ".$i++." WHERE id = '$v'";
mysql_query($q) or die();
}

Related

inserting same query from multiple array

I make a mathematichs function in mysql. and give two result because it`s calculate from 2 records. this is the source :
$calculate= mysql_query("select markers_tujuan.lng,markers_tujuan.lat,open_list.lat, open_list.lng,
((SQRT((((markers_tujuan.lat-markers_tujuan.lng)*(markers_tujuan.lat-markers_tujuan.lng)) + ((open_list.lat-open_list.lng)*(open_list.lat-open_list.lng)))))+(sqrt((((markers_tujuan.lat-open_list.lat)*((markers_tujuan.lat-open_list.lat)))+((markers_tujuan.lng-open_list.lng)*((markers_tujuan.lng-open_list.lng)))))))
as hasil
from markers_tujuan, open_list");
$op=mysql_query("select * from open_list");
$line=mysql_fetch_assoc($op);
/* fetch associative array */
while ($row = mysql_fetch_assoc($calculate)) {
printf ("1(%s %s),(%s %s),%s <br> \n", $row["lng"], $row["lat"], $row["lat"], $row["lng"], $row["hasil"]);
$try=mysql_query(" UPDATE open_list SET hitung = '".$row["hasil"]."' ");
}
and the result is
but I didn`t understand why query in mysql updating same query
As others have pointed out, your UPDATE statement does not have a WHERE condition. Therefore, every single row in your table will be updated, each time:
mysql_query(" UPDATE open_list SET hitung = '".$row["hasil"]."' ");
You should specify the PRIMARY KEY while updating. In this case, it is the column id (I presume). Example:
UPDATE open_list SET hitung = 'example' WHERE id = '4'
You should add SELECT open_list.id,... on your first query and WHERE id = ' . $row['id'] in the update sentence.

Know lower value and its column name from select

I have a PHP document with MySQL database storing with the following structure:
DATE FIELD
24 float values corresponding to the 24 hours. (The name is 1h, 2h, 3h, 4h... 24h)
I fetch a row with the simple select: SELECT * from table where DATE = "2014-02-02" obtaining the 25 fields.
I want to know wich field of 1h, 2h, 3h.... has the lower value. I'm trying doing that with PHP and min() function, but I only retreive the value, not the index of the array.
Is this possible a simple way to know this result? Maybe in the SQL function?
Thank you
EDIT: I tried this (Considering $arraySQL has a valid result obtained before):
function ObtainArrayFromSQL($arraySQL){
$array = array();
for ($i = 1; $i < 25; $i++)
{
array_push($array, $data_day[$i."h"]);
}
return $array;
}
[...]
$array = ObtainArrayFromSQL($arraySQL)
echo min($array);
Assuming you are using MySQL, you can use the least() function:
select t.*,
(case when col1 = leastval then 'col1'
when col2 = leastval then 'col2'
when col3 = leastval then 'col3'
. . .
when col24 = leastval then 'col24'
end) as leastvalcol
from (select t.*,
least(col1, col2, . . . , col24) as leastval
from table t
) t;
Before complaining about all the typing you need, you should know that this query is much more complicated than it needs to be -- because you are storing things on a row that should be in a column. Your table should have a separate row for each hourly value, rather than putting all the daily values on one row. With a more normalized structure, your query would be much simpler.
EDIT:
This table would have columns such as:
Date date,
Hour time, -- or int or varchar() depending on how you really want it captured
Value float
Then the query might look like:
select date, min(value) as minvalue,
substring_index(group_concat(hour order by value asc), ',', 1) as minhour
from newtable t
group by date;
At first, thank you everyone for the help.
Finally I made the solution with PHP instead of manipulate a big SQL sentence.
I create the array using the function ObtainArrayFromSQL, and then, use the function array_search() with min() as needle in the haystack (array).
function ObtainArrayFromSQL($arraySQL){
$array = array();
for ($i = 1; $i < 25; $i++)
{
array_push($array, $data_day[$i."h"]);
}
return $array;
}
...
$index_lower_value = array_search(min($array), $array);
Thank you everyone!

PHP MySQL - Find Row ID

I have a table called "participants" that has 3 fields:
prt_id
prt_event_id
prt_participant_id
What I have is a select query with a where condition on event_id. The query returns let's say 20 rows (20 different participants). What I would like to do is to be able to figure out the row number for a given participant (prt_id).
SELECT *
FROM participants
WHERE prt_id = someinteger
While you can't specifically find a row ID using MySQL, you could do something like the following:
$conn = new mysqli(/*dbinfo*/);
$res = $conn->query("SELECT prt_id FROM participants");
$rowids = array(); $currid = 1;
while ($row = $res->fetch_object()) { // this is using the mysqli library
$rowids[$row->prt_id] = $currid;
$currid++;
}
This would give you an array of ids associated with prt_id.
You could do something like:
<?php
$counter = 1; // Start at one for first entry
$res = mysql_query("SELECT * FROM participants WHERE prt_id = 12");
while( $array = mysql_fetch_assoc($res) )
{
// Do something with the counter, store it into array with details
$counter++;
}
?>
This should do what you want inside MySQL (ie assign a rownum in the order of prt_id), but the performance will be dependent on the number of rows in the table so it's not optimal.
SELECT * FROM (
SELECT #tmp:=#tmp+1 rownum, p.*
FROM (SELECT #tmp:=0) z, participants p
ORDER BY prt_id
) participants
WHERE prt_id = 36;
Demo here.
Edit: This "doh level" rewrite uses an simple index range instead of a table scan, so should be much faster (provided prt_id is a PRIMARY KEY)
SELECT *, COUNT(p2.prt_id) ROWNUM
FROM participants p1
JOIN participants p2
ON p1.prt_id >= p2.prt_id
WHERE p1.prt_id=36;
Demo here.
you could just add an index column in your database, set it as int, primary key and auto increment. then when retrieving the row you retrieve the index number.
RowID is a feature of Oracle: http://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns008.htm.
MySQL does not have something like that, you can basically emulate that by assign number to an array inside php as you retrieve each row, but that doesn't guarantee you the same number next time you retrieve that results. You probably have to settle for using one of the primary IDs

sql php find field value from updated row

Say I have this loop:
foreach ($array as $a) {
if ($a == $b) {
mysql_query("UPDATE table SET this = 'that' WHERE id='$a'");
}
}
And a table...
id this blah
------------------------
1 that 54
2 that 73
3 there 27
Inside that loop, I also want to find the value stored in the tables blah field from the current record that is being updated.
Whats the most effective way to do this?
You can have your query consist of multiple statements, and the last statement is what is used for the "results".
So, you can just add a "select" statement to the end of the update query and treat it like a normal select statement:
UPDATE table SET this = 'that' WHERE id='$a'; SELECT blah from [your table] WHERE id = '$a'
The advantage with this method is that it doesn't require an additional DB call.
Of course, you will want to be escaping the values put into the SQL statements to prevent SQL injection, but that's another matter.
Update
This was my first second SO answer which I felt needed revising. Searching around, I found a much better answer to your question.
From the accepted answer for question: SQL: Update a row and returning a column value with 1 query
You want the OUTPUT clause
UPDATE Items SET Clicks = Clicks + 1
OUTPUT INSERTED.Name
WHERE Id = #Id
Similar question: Is there a way to SELECT and UPDATE rows at the same time?
Old Answer
Add a SELECT statement to the end of your UPDATE query.
mysql_query("UPDATE table SET this = 'that' WHERE id='$a'; SELECT blah WHERE id='$a';");
This prevents you from ensuring the update took place since mysql_query only returns the last statement's result.
You could also write a custom function that performs both statements but, for instance, won't preform the SELECT if the UPDATE failed, etc.
** Skeleton Function - Not Tested **
function MyUpdate($query, $id){
$retVal = "-1" // some default value
$uResult = mysql_query("UPDATE table SET this = 'that' WHERE id='$a'");
if( $uResult )
$result= mysql_query('SELECT blah WHERE id=$a');
if (!$result) {
die('Invalid query: ' . mysql_error());
}
$retVal = $result;
}
return $retVal;
}

How to find missing data either in array or in mySQL table?

I have an array filled with values (twitter ids) and I would like to find the missing data between the lowest id and the highest id? Any care to share a simple function or idea on how to do this?
Also, I was wondering if I can do the same with mySQL? I have the key indexed. The table contains 250k rows right now, so a temporary table and then a join wouldn't be very fast or efficient. I could do a PHP loop to loop through the data, but that would also take a long time, and a great deal of memory. Is there a specific mysql query I can run? or can I somehow use the function from above with this?
Thanks,
James Hartig
http://twittertrend.net
I had a similar requirement and wrote a function that would return a list of missing IDs.
---------------------------
create function dbo.FreeIDs ()
---------------------------
returns #tbl table (FreeID int)
as
begin
declare #Max int
declare #i int
select #Max = MAX(ID) from [TheTable]
set #i = 0
while #i < #Max begin
set #i = #i + 1
if not exists (select * from [TheTable] where ID = #i)
insert into #tbl select #i
end
return
end
Do you mean sequential ID's?
In that case
$new_ids = range($lowid, $highid, 1);
$ids = array_merge($ids, $new_ids);
$ids = array_unique($ids);
sort($ids);
And in SQL (with placeholders)
SELECT key, other_data from `table` WHERE key > :low_id AND key < :high_id
Your range() gave me a good idea, your code didn't work as unique preserves unique keys, so I was just left with the range functions result.
However, this worked:
$diff = array_values(array_diff(range(min($array), max($array), 1), $array)); //returns array of incomplete values

Categories