Mysql Select random rows to n times - php

I want to get 3 random records from my table to 90 times.
Scenario
user_id number_of_bids
12 20
8 40
6 30
what i want is...Get above 3 rows in random order to a specific number In fact it is sum(number_of_bids)...
And every row should not repeated greater than its number of bids..
I have created a query where I am getting sum of number_of_bids.Now second query required where these 3 records should be in random order to sum(number_of_bids) times and every record should not greater repeated greater than its number_of_bids.
Not sure it can be achieved in one query or not.But you people are experts I am sure you can help me.It will save my execution time..
Thanks..

I would just build an array out of the rows and shuffle it:
$stmt = $db->query('SELECT user_id, number_of_bids FROM table_name', PDO::FETCH_KEY_PAIR);
$results = array(); $startIndex = 0;
foreach ($stmt as $userId => $numberOfBids) {
$results += array_fill($startIndex, $numberOfBids, $userId);
$startIndex += $numberOfBids;
}
shuffle($results);
Then, you can iterate $results however you'd like.

Related

How do you do a count query in php with a where clause?

So I have this query like this
$sql2 = "SELECT count(*) FROM comments WHERE YourUsername = '$MyUsername' AND PostId = '$PostId'";
if ($result2=mysqli_query($conn,$sql2))
{
// Return the number of rows in result set
$rowcount=mysqli_num_rows($result2);
echo $rowcount;
}
and I have 2 rows in my database which meet the clause requirements but for some reason it keeps outputting 1 as the result. How do I make it display the actual count and not just 1 when in reality the count is 2 and so on for future rows.
You're SELECTing the count of the rows in your first line, so when the query is run, it's returning the row count into $result2. You don't need to use mysqli_num_rows.
Foul

Identifying the number of rows within a specific value range using PHP

I am trying to figure out how to determine the total number of rows within a specific number range using PHP.
I have a simple MySQL table with a single column. The column contains thousands of rows, each row containing a number between 0 and 100.
I figured out how to find the number of rows for a specific number, using array_count_values, but I can't figure out how to find the number of rows for a range.
For example, how many numbers are there between 60 and 80?
Here is the code that I put together to find a single value. What code should I add to find range values?
$query = "SELECT numbers FROM table";
$result = mysqli_query($conn, $query) or die("Error in $query");
$types = array();
while(($row = mysqli_fetch_assoc($result))) {
$types[] = $row['numbers'];
}
$counts = array_count_values($types);
echo $counts['12'];
If you need to count within multiple ranges you can use UNION so you don't have to send 5 queries.
$query = "SELECT COUNT(numbers) FROM `table` WHERE numbers between 00 and 20
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 20 and 40
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 40 and 60
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 60 and 80
UNION ALL
SELECT COUNT(numbers) FROM `table` WHERE numbers between 80 and 100";
You can do this several ways.
Simple way (one full table scan)
SELECT SUM(IF(x BETWEEN 20 AND 30, 1, 0)) AS b_20_30,
SUM(...) AS b_31_40,
...
FROM tableName...
will return only one row with all your results in the time of a table scan.
Fancy way (not really recommended)
If you can come up with a rule to map your intervals to a single number, for example:
0...9 => interval i = 0
10...19 => interval i = 1 => the rule is "i = FLOOR(X/10)"
20...29 => interval i = 2
...and you don't need to scan too many rows, you might do something not very maintainable like this:
SELECT SUM(FLOOR(POW(100, FLOOR(x / 10)))) AS result FROM tableName;
Here, a value of 25 (between 20 and 29) will become 2, and the total sum will be increased by 1002. So long as you never have more than 100 rows in each group, the final result will be a univocal sum of powers and, if you have - say - 17 rows between 0 and 9, 31 rows between 10 and 19, and 74 between 20 and 29, you'll get a "magical parlor trick" answer of
743117
from whence you can recover the number of rows as 74,31,17 in that order.
Using 1000 instead of 100 would yield 74031017 (and the possibility of coping with up to 999 numbers in each group).
Note that the use of functions inside the SELECT pretty much guarantees you'll need a full, slow table scan.
Using indexes for speed
But we can get rid of the table scan, and simplify generation, by judiciously using indexed WHEREs - this is identical, performance-wise, to a UNION, but the result is simpler since it is only one row:
SELECT (SELECT COUNT(*) FROM tableName WHERE x BETWEEN ...) AS b_20_30,
(...)
; -- no table name on the outer query
This will need several subqueries (one per interval), but those subqueries will all use an index on x where available, which can make the overall query very fast. You just need
CREATE INDEX x_ndx ON tableName(x);
The same index will greatly improve the performance of the "simple" query above, which will no longer need a table scan but only a much faster index scan.
Build the query using PHP
Supposing we have the intervals specified as convenient arrays, we can use PHP to generate the query in the first place. No need of manually entering all those SELECTs.
$intervals = [ [ 20, 30 ], [ 17, 25 ], ... ];
function queryFromIntervals(array $intervals) {
$index = 0;
return 'SELECT ' .
implode(',', array_map(
function($interval) use ($tableName, &$index) {
return "(SELECT COUNT(1) FROM {$tableName} WHERE x BETWEEN {$interval[0]} AND {$interval[1]}) AS b_" . ($index++);
},
$intervals
))
// . ", (SELECT COUNT(*) FROM {$tableName}) AS total"
. ';';
}
This will again yield a single row, with fields named b_0, b_1, and so on. They will contain the number of rows where the value of x is between the bounds of the corresponding interval in $intervals (the intervals may overlap).
So by executing the query and retrieving a tuple called $result, you might get
[ 'b_0' => 133, 'b_1' => 29 ]
meaning that there are 133 rows with x between 20 and 30, and 29 with x between 17 and 25. You can add to the query a last total field (commented in the code above):
, ... ( SELECT COUNT(*) FROM tableName ) AS total;
to also get the total number of rows.
The same function, changing the inner return value, can be adapted to generate the "simple" query which uses IFs instead of SELECTs.
Why not let the database do the heavy lifting for you?
$query = "SELECT COUNT(*) FROM table WHERE numbers BETWEEN 60 AND 80";
$result = mysqli_query($conn, $query) or die("Error in $query");
$row = mysqli_fetch_array($result, MYSQLI_NUM);
echo $row[0];
If I understood well, you try to put a condition in your request sql.
Look that https://www.w3schools.com/sql/sql_where.asp
$query = "SELECT numbers FROM table WHERE numbers >= 60 AND numbers <= 80";

need help to find a php structure solution

I am just a student at php, I am trying to find out a list of members from a table where I dont know how much rows are in that table, but I need every 6 rows on Order By entrytime DESC basis.
My table structure is as below:
int `ID`
int `entrytime` // this time updates when rows insert
now I need to find out all ids on basis of entrytime DESC and insert those ids in a separate new table say "new_tbl" as a group of 6 ids
ind `ID`
varchar `group_name`
I am trying to do like this :
$qry=mysql_query("SELECT id FROM main_table entrytime ASC");
while($res=mysql_fetch_row($qry)){
$id=$res['0'];
$q=mysql_query();
######### But not getting any Idea how to find every 6 Ids and insert in new_tbl #######
}
In your case you use mysql_fetch_row this gives you the count of rows and not the data.
while($res=mysql_fetch_assoc($qry)) {
To get the Data you have to use mysql_fetch_assoc for example.
To find every 6 Ids you can make a counter and increment the value by 1. If the modulo of 6 and the value is 0 you have the sixth value and you can reset the counter.
$i = 1;
while ...
if($i % 6 == 0) {
// reset your counter
$i = 1;
}
$i++;
}
Then you can use the counter to work with it and write that to another table for example.

Query returning additional empty variable

I'm running into some weird behaviour when calling values with SQL.
$result = mysqli_query($conn,"SELECT DISTINCT value FROM table ORDER BY value ASC");
while($row[] = mysqli_fetch_array($result));
$maxcat = count($row);
There are 8 unique values in my table, yet $maxcat returns "9". Am I missing something? I'm using the information to populate a list of categories. I knew I'd have to subtract one from maxcat to allow for $row[0], but I'm having to subtract two to make up for this empty value that won't get lost.
for ($i=0; $i<=($maxcat-2); $i++)
Cheers!
Thanks #scrowler & #faintsignal! Using mysqli_num_row() rather than count() is exactly what I needed. Functioning code below.
$result = mysqli_query($conn,"SELECT DISTINCT value FROM table ORDER BY value ASC");
$maxcat = mysqli_num_rows($result);
while($row[] = mysqli_fetch_array($result));
The while condition gets evaluated once for every row in your query result, plus one additional time to detect that there are no more rows left. So if you have 8 rows in your result, the while condition is evaluated 8 + 1 = 9 times. Hence you add 9 entries to your array $row, the final entry having the value NULL.
Note, if your while loop had a body, that body would only be iterated 8 times because the 9th time the condition would evaluate to false.
As #scrowler pointed out, if you just want to count the number of rows in the result, you can simply use mysqli_num_rows.

SUM SQL value to increment values per session

This is very awkward, this is a very simple fetch value, equal to otherwise sum one and then save... but is not working...
I have a predefined value as 1010, so, I select the last entry in the SQL, if the last entry is grater than 1010 then get the value and add 1, then save it which now the last value would be 1011 correct? but is not....
$values_b = 1010;
$getval = 'SELECT number FROM table ORDER BY number DESC LIMIT 1';
$final = $con->query($getval);
$vals = $final ->fetch_array();
$numbers = $vals['number'];
if ($numbers > 1010){
$new_n = $numbers + 1;
$new_numbers = 'INSERT INTO table (number) VALUES ('$new_n')';
$con->query($new_numbers);
} else {
$new_numbers = 'INSERT INTO table (number) VALUES ('$values_b')';
$con->query($new_numbers);
}
Very simple, but the result some how is awkward, it doesn't save 1010 or 1011 or any of the sort... instead is saving 2325 and why is that???? I don't use this values anywhere else, those are unique variables but I really don't understand, this is the first time this is happening, my table is utf-8-general-ci and the column is INT(20) I have try VARCHART(100) but the result is almost the same...
What I'm trying to achieve is "simple", I have a per-defined number 1010, so, if this is the first record save that number 1010, if not, then get the last record say 1020 which mean that there are 10 records, just sum 1 to the last record 1020 + 1 = 1021 and save it... see, very simple, but for some reason is not doing it... so I was wondering if someone can help me solve this...
Thank you for taking the time
SOLVED
The problem here was the query, I was calling to a column with the incorrect name
this table has about 19 columns, the first 5 are
ID | Name | email | numbers ..... the column 16 is | number |
I was calling number when in reality I should be calling for NUMBERS the result that I was getting was from another file, so, in other words, I was getting the result from B and adding 1 to B when I should be using A...
this is entirely my fault, I should paid more attention... sorry guys...
Try this:
$values_b = 1010;
$getval = 'SELECT max(number) as bignumber FROM table';
$final = $con->query($getval);
$vals = $final ->fetch_array();
$numbers = $vals['bignumber'];
if ($numbers > 1010){
$new_n = $numbers + 1;
$new_numbers = 'INSERT INTO table (number) VALUES ('$new_n')';
} else {
$new_numbers = 'INSERT INTO table (number) VALUES ('$values_b')';
}
$con->query($new_numbers);

Categories