简体   繁体   中英

MySQL apply a value a field of each row based on the order of another field

I have a table which I would like to apply a price rank for each record.

1 for the highest, 2 for the next highest, 3 for the next highest.

Currently I'm selecting each row and then updating each record individually like so:

Usage: function get_list('table','order field','order direction') - returns associative array

foreach(get_list('ps2','price','DESC') as $p)
{
    $ct++;
    $s = "UPDATE `ps2` 
            SET `price_rank` = '".$ct."' 
            WHERE `db_id` = '".$p[db_id]."'
            LIMIT 1";
    mysql_query($s);
}

As I have many records this is extremely slow, is there another way?

Edit: Here's one way which is way faster but is there a better way?

ALTER TABLE `ps2` DROP `price_rank` ;
ALTER TABLE `ps2` CHANGE `db_id` `db_id` INT( 11 ) NOT NULL ;
ALTER TABLE `ps2` DROP PRIMARY KEY ;
ALTER TABLE `ps2` ORDER BY `price_per_pax_after_tax` DESC;
ALTER TABLE `ps2` ADD `price_rank` INT NOT NULL AUTO_INCREMENT PRIMARY KEY;
ALTER TABLE `ps2` ORDER BY `db_id`;
ALTER TABLE `ps2` CHANGE `price_rank` `price_rank` INT( 11 ) NOT NULL ;
ALTER TABLE `ps2` DROP PRIMARY KEY ;
ALTER TABLE `ps2` ADD PRIMARY KEY ( `db_id` ) ;
ALTER TABLE `ps2` CHANGE `db_id` `db_id` INT( 11 ) NOT NULL AUTO_INCREMENT ;

Personally I would handle the ranking in the DML statements using aggregate functions like MAX and limit and offset to get the results I want. Also when the price changes you will have to repopulate the rank values if you store them in the table. The current methods above do not handle identical prices.

You can return the rank without storing it with this

SELECT p.db_id, COUNT(DISTINCT p2.price) as Rank 
FROM packages_sorted as p 
JOIN packages_sorted as p2 ON p.price <= p2.price 
GROUP BY p.db_id 

If you still want to store the rank,

UPDATE FROM packages_sorted as p JOIN (
    SELECT p.db_id, COUNT(DISTINCT p2.price) as PriceRank 
    FROM packages_sorted as p 
    JOIN packages_sorted as p2 ON p.price <= p2.price 
    GROUP BY p.db_id
) as pSub ON p.db_id = pSub.db_id 
SET p.price_rank = pSub.PriceRank 

Both of those statements handle identicle prices with the count distinct.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM