Select the highest number in mysql - php

I am developing a trading site. Users will post some price, $100, $120 for certain products. And I wanted to display highest price for that product, which means current highest price will replace the previous highest price. Tables of mysql is:
user_email //The user who gives price for the product
product//The product name
price//The prices that users posted
chosen//it will be 1 if it is highest otherwise 0
What I wanted to do is that if a user posted $100 for, for example, a book and it is currently highest price (chosen is one for this user) and site displays it. Another user posts $120 for that book and it is now highest price (chosen is 1) and for the previous user's chosen is 0. I could not figure out how to compare prices for certain products and change all of the lower prices chosen 0 for that product. How can i do this? Sorry i am new:(

You can use the MAX function from MySQL to get the highest number of a colomn. Example :
SELECT MAX(field) FROM `table_name`
You just need to add WHERE and it will confine the search fields.
After, you update everything else with something like this
UPDATE `table_name` SET `field` = 0 WHERE `product` = "X" AND `id` != Y
X will be the product ID and Y will be the ID from the first query.

Something like this will do you,
$q = $dbc -> prepare("SELECT price FROM table_name ORDER BY price DESC LIMIT 1");
Using the order by clause will get you the highest price available, now store it in a variable like so,
$q -> execute();
$highest = $q -> fetch(PDO::FETCH_ASSOC);
Now change all the other users' price to zero,
$q = $dbc -> prepare("UPDATE table_name SET price = 0 WHERE price != ?");
$q -> execute(array($highest));
Now this will eliminate the need for the chosen column in your database, as you only need the highest price for a bid, which can easily be found using the opposite of the above query with another parameter for the BID ID.
This example is using PDO which I highly suggest if you are making a trading site, I hope this was what you wanted to achieve,
Happy coding,

Related

Count how many rows it takes to reach certain query

I have a pretty simple query,
$query3 = $db->query("SELECT * FROM mybb_ranks WHERE id='1' ORDER by points DESC");
And what it'll return is a database of people who are registered and ranked. Since players points can be randomly changing due to matches, we determine the rank # by assigning it once the value is fetched in a way like this:
$i = 1;
while($row = mysqli_fetch_array($query5))
{
echo "$row[player]'s rank is $i";
$i++;
}
As you can see, it orders the player's by their points, but determines the rank # from a variable that adds after displaying every rank. However, in each of the user profiles, I would like to display their rank as well. This is a bit more difficult, because I need a certain way to count the amount of rows the query has to go through in order to get to the certain player. So for instance, if PlayerB is ranked at #5, I would need a way to display that on his own profile. For this to happen, I imagine the query would need to be altered to be able to count each individual row (4 rows) before it reaches the certain player on the 5th row. I was wondering, how would I go about this?
Try this:
UPDATE mybb_ranks
LEFT JOIN (
SELECT
player,
#rank:=#rank+1 as current_rank
FROM mybb_ranks
WHERE id='1'
ORDER BY points DESC
) AS t
ON mybb_ranks.player = t.player
SET mybb_ranks.rank = t.current_rank
That means you have to create additional column rank in your mybb_ranks table.
This query will update the rank of user each time you generate your ranks list.
So when you need to show user's rank in his profile page you just request it from the table:
SELECT rank
FROM mybb_ranks
WHERE player = :player_id
if you want it more dynamic, you can run this UPDATE query every time when you generate your player profile page, right before SELECT rank.

How can i sort a mysql result by a list of prioritised ids?

I have a large products database, and every sunday, my script is activating 50 new products.
the thing is, based on some rules in my script, im finding some products i should prioritize activating. (for your example, lets say it should always prioritize activating products with the name 'hello kitty' and 'meshuggah' in them, before everything else)
my db table contains info about the product, and unique id.
lets say that the script finds 5 of these ids, having hello kitty in the title.
so, how can i make the query, so that the prioritized items will come on top, and then followed by id desc?
here some pseudocode of what im after:
SELECT * FROM products order by (id='59', id='47', id='28', id='29', id='20'), id desc limit 50
the result should give me id 59, 47, 28, 29 and 20 first, then followed by other ids in the products table sorted by id descending.
is that possible in one query?
use FIELD
SELECT *
FROM products
order by FIELD(id,59,47,28,29,20), id desc
limit 50
Ordering by specific field values with MySQL
Actually, your pseudo code also comes pretty close to such a query:
SELECT *
FROM products
order by id='59' desc, id='47' desc, id='28' desc, id='29' desc, id='20' desc, id desc
limit 50
This uses the fact that a condition evaluates to 0 or 1.

Mysql insert current result and then insert new result

I have an ajax live table edit to change the price of my current product. What I want to do is insert the price before I change it and then insert the updated price. The reason being is because I want to show the change in the updated price. Example: current price is $54.00 and I change it to $57.00. I need to keep a log of price change throughout the day and show the price change of $3.00. How would I go about inserting the old price while the updated price gets inserted also. Thanks.
I suggest you make your price table like this
table price
-----------
id unsigned integer autoincrement primary key
article_id integer /*link to articletable*/
valid_from date
valid_until date
amount decimal(10,2) /*always use decimal for money*/
Then you can insert your new price using the following 4 queries.
/*hide changes from the rest of the world until we are done*/
START TRANSACTION
/*invalidate the latest existing price in the price table*/
UPDATE price
SET valid_until = DATESUB(CURDATE(),INTERVAL 1 DAY)
WHERE article_id = '100' ORDER BY valid_until DESC LIMIT 1
/*the order by selects the latest item, the limit does only 1 update*/
/*insert the new price*/
INSERT INTO PRICE (article_id, valid_from, valid_until, amount)
VALUES ('100', CURDATE(), DATEADD(CURDATE(),INTERVAL 100 YEAR), '99.95')
/*show changes to the rest of the world*/
COMMIT
You need the transaction or you risk the price table being out of sync. Set the tabletype to InnoDB on the price table.
Al your other tables can be MyISAM, just make sure the price table is InnoDB.
You can now select prices by using:
SELECT article.name
,price.amount as price_per_item
,purchase.qty as number_of_items
,price.amount * purchase.qty as amount
FROM purchase
INNER JOIN article ON (article.id = purchase.article_id)
INNER JOIN price ON (price.article_id = purchase.article_id)
AND (purchase.transactiondate BETWEEN price.valid_from and price.valid_until)
WHERE purchase.id = '458'
you can maintain to different fields for the two. Like old_value and new_value. At the end of the day you can tally the values and print the difference.

How can I show my ads an equal number of times?

I'm building my own advertisement platform, and I have a little problem. How can I show my ads an equal number of times?
So for example:
Name | Views
Ads 1 | 100
Ads 2 | 98
Ads 3 | 99
So my system need to show the ads with the least views, in this case "Ads 2 or Ads 3".
So all my ads follow each others views. So when my 3 ads have 3.000 views total, there should be 1.000 views on every view.
I'm coding in PHP, and I don't have an example, because I need inspiration how to fix my problem.
Select your least viewed add like this:
SELECT * FROM ads ORDERBY views ASC LIMIT 0, 1
This way, all the ads with less views will slowly catch up.
-- Edit, using your next requirement
probabilityForHighestScore = 30;
random = rand(0, 100);
if (random > probabilityForHighestScore)
SELECT * FROM ads ORDERBY views ASC LIMIT 0, 1
else
SELECT * FROM ads ORDERBY score DESC LIMIT 0, 1
If you need something else, you'd better explain you whole requirement first. Because if it is not clear for you, it won't be clear in your question, and the answers won't do what you want.
I'm assuming you have a database table containing information about these ads. You could add, if you don't already have it, a views field to that table. Then, whenever you need to display an ad, you just grab the one with the lowest view count, add 1 to it's view counter, and display the ad.
Edit:
The problem with #MarvinLabs solution, as I explain in the comments, is that it's giving a huge bonus to a single record.
Let's say you have 50 separate ads in your system. Let's also say that your highest scoring record has a score of 9.9/10, and your second highest scoring record has a score of 9.8/10. Both of these are very high scoring items, but if you use #MarvinLabs code, the highest scoring record will get 30% of all views, while the second highest scoring record will get 1.4% of all views (70 percent of all views divided across the 49 non-highest scoring ads).
What you might want to consider is allowing for a larger range of high scoring ads to be included. You can do this in any one of three ways:
First, you can set a threshold, or multiple thresholds, which divide a certain percentage of views to certain ranges of scores. For example, you could have it so that ads which score more than 9/10 get 30% of all views. You would do that like this:
$random = rand(1,100);
if ($random > 30) {
$sql = "SELECT * FROM ads WHERE score >= 9 ORDER BY views ASC";
} else {
$sql = "SELECT * FROM ads WHERE score < 9 ORDER BY views ASC";
}
The problem with this is that if you don't have any ads with a score above 9, you won't get anything back. For that reason, you probably don't want to use this method.
Second, you could spread your 30% of views across the top 5 or 10 ads:
SELECT *
FROM ads
WHERE id IN
(SELECT id
FROM ads
ORDER BY score DESC
LIMIT 10)
ORDER BY views ASC;
This solves the problem of "what if I don't have any records above the threshold" while still spreading the "high score bonus" across more than just a single record. The problem with this, if you consider it a problem that is, is that it doesn't scale with the volume of ads you have on record. Whether you have 10 records or 10,000 records, you'll still give the bonus to just 10 (or 20, or 50.. whatever you set) records.
If you want to scale, you'll want the third solution.
The third solution is to set your limit based on a percentage of the total number of records in the table. Since MySQL doesn't have a built-in way of handling this, you'll need to workaround this in one of two ways:
One way to do it the lazy way and run two queries - one to get the current record count, and another to create a query based on it. For example:
$query1 = "SELECT COUNT(*) FROM ads";
//store result in $count
$percentage = round($count * 0.10); //get 10% of records
$query2 = "SELECT * FROM ads WHERE id IN " .
"(SELECT id " .
" FROM ads " .
" ORDER BY score DESC " .
" LIMIT " . $percentage . ") " .
"ORDER BY views ASC"
A better way would be to avoid the second round-trip to the database and use a prepared statement:
SELECT #percentage := ROUND(COUNT(*) * 10/100) FROM ads;
PREPARE PERCENTAGE FROM
SELECT *
FROM ads
WHERE id IN
(SELECT id FROM ads
ORDER BY score DESC
LIMIT ?)
ORDER BY views ASC;
EXECUTE PERCENTAGE USING #percentage;

finding the number of 1's in my table in order

I have a table of customers with a 1 recorded against their customerid on different dates.
I would like to find the sum of the 1's recorded in descending order. I'm using MySQL and php
Thanks
My guess is that you want the sum of records marked with 1 per customer and sort that result in descending order? If so, the following should do the trick :
select cust.id, sum(cone.one) as number_ones
from customers as cust
inner join customer_ones as cone on cone.id=cust.id
group by cust.id
order by number_ones desc
This is assuming that 'one' is the column containing ones (and only contains 0 or 1 - otherwise you will have to add WHERE cone.one = 1), customers is your customer table and customer_ones is the table containing your customer data.
As i get you right, this is simple sql request what u need:
SELECT COUNT(id) as total from customers
Just make in php:
$sql="SELECT COUNT(id) from customers";
$query=mysql_query($sql) or die(mysql_error());
$res=mysql_fetch_assoc($query);
$summ=$res['total']; //<- Your summ (i.e. quantity of rows in table)
Btw, you can use mysql_num_rows instead.
Or explain please more accurately what output you need. To make sorting by date or any other dependency you will need to make other request using WHERE clause and date comparison.

Categories