Reputation: 758
I have a table, named city.
city_name
---------------
New York
Beijing
New York
New York
Dubai
Beijing
---------------
After update, I want it be:
city_name, index
---------------
New York, 0
Beijing, 0
New York, 1
New York, 2
Dubai, 0
Beijing, 1
---------------
The pattern is like this: the first New York will be have an index of 0, the second New York's index is 1 and the third one will be 2. There are millions of rows in this table.
Any easy way to make this update?
I am thinking to solve this problem in two step.
First step:
@cities = Select distinct city_name from city;
Second step:
foreach @cities as @city
update city set index = row_num where city_name = @city.cityname
It seems row_num is not availbe in mysql.
Upvotes: 1
Views: 67
Reputation: 1270713
Try this:
update city cross join
(select @city := '', @prevcity := '', @i := 0) const
set `index` = (case when (@prevcity := @city) is null then null
when (@city := city) is null then null
else @i := if(@prevcity = city, @i + 1, 1) is null then null
end)
order by city;
If you are familiar with the use of variables for enumeration in a select
statement, then this is similar. The complication is ensuring the order of evaluation for the update
. This is handled by using a case
statement, which sequentially evaluates each clause until one is true. The first two are guaranteed to be false (because the values should never be NULL
).
EDIT:
If you have a unique id, then the solution is a bit easier. I wish you could do this:
update city c
set `index` = (select count(*) from city c2 where c2.city = c.city and c2.id <= c.id);
But instead, you can do it with more joins:
update city c join
(select id, (select count(*) from city c2 where c2.city = c1.city and c2.id <= c1.id) as newind
from city c1
) ci
on c.id = ci.id
set c.`index` = ci.newind;
Upvotes: 2
Reputation: 5991
A way to do this using session() for storage AND comparing purposes:
session_start();
$number=0;
$result=mysqli_query($yourconnection,"SELECT * FROM city ORDER BY city_name");
while($row=mysqli_fetch_array($result)){
if(empty($_SESSION["storage"])){
/* THIS CONDITION ONLY GOES THROUGH THE VERY FIRST ARRAY FETCH */
$_SESSION["storage"]=$row['city_name'];
mysqli_query($yourconnection, "UPDATE city SET index='$number' WHERE city_name='$cityname'"); /* STORE TO THE FIRST CITY'S INDEX 0 */
}
else if($_SESSION["storage"]==$row['city_name']){
/* IF SESSION IS THE SAME COUNTRY AS THE CURRENT ROW COUNTRY */
$_SESSION["storage"]=$row['city_name'];
$number=$number+1; /* INCREMENT NUMBER FOR THE SAME COUNTRY */
mysqli_query($yourconnection, "UPDATE city SET index='$number' WHERE city_name='".$row['city_name']."'");
}
else {
/* THIS IS FOR THE NEXT NEW COUNTRY */
$number=0; /* START AGAIN THE COUNT TO 0 IF NEW COUNTRY */
$_SESSION["storage"]=$row['city_name'];
mysqli_query($yourconnection, "UPDATE city SET index='$number' WHERE city_name='".$row['city_name']."'");
}
} /* END OF WHILE LOOP */
I've done this before, but with different output but with the same logic. AND I use another table for storage purposes and comparing purposes. But the code above that I've made, I used session instead.
Upvotes: 1