Php how to check for duplicate results? - php

Hi I'm currently querying from a database base user ids for a contest, However I want to avoid choosing duplicates in my results_array, this function getrandomspecies receives a array_result, this array results iterates 7 times. How test that I don't put duplicates in my results_array? I have gotten several duplicates.
function getrandomspecies($array_result){
//database connection
$dbn = adodbConnect();
foreach($array_result as $possible){
//query the results
$querys= "select * from taxonomic_units where tsn = $possible";
$resultss = $dbn -> Execute($querys);
while($rowss=$resultss->FetchRow()){
$id = $rowss['tsn']; //there ID
$ranksss = $rowss['rank_id']; //ranking id, I choose 220 and 230
if($ranksss == 220 || $ranksss == 230){
$prelimary_array[] = $id;
}
}
//grab random index
$index = array_rand($prelimary_array,1);
//put result id into a variable
$newspecies = $prelimary_array[$index];
//put that variable in an array
$results_array[] = $newspecies; //there is 7 newspecies/winners at the end, I dont want duplicates
}
return $results_array;
}

MySQL should be the following :
select distinct tsn, rank_id from taxonomic_units where tsn = $possible
But you should ideally use prepared statements.

what about this? You may do it with one query:
$querys= "select DISTINCT tsn from taxonomic_units where tsn IN (".implode(",",$array_result).") AND rank_id IN (220,230) ORDER BY RAND() LIMIT 7 ";

Loop your result array and if it does not exists add it. If you end up with less than 7, do your big loop again.
replace this line :
$results_array[] = $newspecies;
by:
$loop_1_more_time=0;
if (isset($results_array)){
foreach($results_array as $result){
if ($result == $new_specie){
$loop_1_more_time=1;
}
}
}
if ($loop_1_more_time == 0){
$results_array[] = $newspecies;
}
//there, if $loop_1_more_time equals 1, start again. To start again and be sure you have seven instead of 6 or less, You could replace your big first "foreach" loop with a "for" loop that depends of the count() of the $array_result, and the $array_result would be array_result[$i] instead of $possible. $i would start at 0 and increment at each end of loop. It would not be incremented if ­­$loop_1_more_time==1;.
Example :
for ($i = 0; $i < count($array_result); $i++) {
//stuff
//if ($loop_1_more_time=1;) { $i--; }
}

Why don't you try shuffling the array, and then picking the first X numbers?
That way, rather than having to check the results array for duplicates, it will never come up in the first place

Related

How to create unique number for each box on order

The issue is not how I am generating the number, that is working fine for a different app I have. The issue is counting the total number of boxes and iterating through a forloop that many times. Right now I am multiplying box_ct * qty_ord to get the total boxes. BTW, I am still trying to understand everything I can do with foreach and for loops, so if anyone has a better idea, Great.
CLARIFICATION: I am searching the database by order number and pulling back qty_ord, box_ct, and item_no for each. On some orders there is more than one item. So for each item I need to multiply qty_ord by box_ct = count and for that specific item I need to iterate through the loop based on what my count is.Right now if I remove the foreach and hardcode the for loop count variable it works fine. Any ideas on what is wrong with my foreach?
qty_ord | box_ct | item_no
------------------------
1 2 10001
3 3 10002
2 1 10003
2 3 10004
2 6 10005
Below is my code.
$sql ="SELECT imitmidx_sql.box_ct, oeordlin_sql.item_no, oeordlin_sql.qty_ord
FROM imitmidx_sql
JOIN oeordlin_sql ON oeordlin_sql.item_no = imitmidx_sql.item_no WHERE ord_no ='$orderNum'";
$query = odbc_exec($conn, $sql);
$row7 = odbc_fetch_array($query);
foreach($row7['item_no'] as $item){
$count = $row7['qty_ord'] * $row7['box_ct'];
for($counter = 0; $counter <= $count; $counter++){
//GRAB NUMBER FROM FILE
$sscc = file_get_contents("ucc128.txt");
//INCREMENT NUMBER
$sscc++;
//PUT THE NUMBER BACK IN FILE
$sscc = file_put_contents("ucc128.txt", $sscc);
//COMBINE STATIC NUMBER AND NUMBER FROM FILE
$ssccnumber = "00950000".$sscc;
//CREATE CHECK DIGIT MATH
$ssccnumArray = str_split((string)$ssccnumber);
$ssccstep1 = array_combine(range(1, count($ssccnumArray)), $ssccnumArray);
$ssccstep2 = 0;
$ssccstep4 = 0;
foreach($ssccnumArray as $k => $v){
if($k%2){
$ssccstep2 += (int)$v;
}else{
$ssccstep4 += (int)$v;
}
}
$ssccstep3 = (int)$ssccstep2 * 3;
$ssccstep5 = (int)$ssccstep3 + (int)$step4;
$ssccCheckDigit = (ceil($ssccstep5 / 10) * 10) - $ssccstep5;
//END CREATE CHECK DIGIT
//CONCATENATE FULL NUMBER
$sscc1 = $ssccnumber.$ssccCheckDigit;
$sql = "INSERT INTO ucc128 (sscc, ord_no) VALUES ('$sscc1' ,'$orderNum')";
#echo $sql.'<br />';
odbc_exec($connPRONUMBER, $sql);
}
}
I believe your issue may be with the following:
foreach($row7['item_no'] as $item){
$count = $row7['qty_ord'] * $row7['box_ct'];
//...
}
This should be:
foreach($row7['item_no'] as $item){
$count = $item['qty_ord'] * $item['box_ct'];
//...
}
You are grabbing data from the query results, as opposed to the current row.
My foreach was not working, so what I did instead was get the sum using my SQL query.
SELECT SUM(imitmidx_sql.box_ct * oeordlin_sql.qty_ord) AS total
FROM imitmidx_sql
JOIN oeordlin_sql ON oeordlin_sql.item_no = imitmidx_sql.item_no WHERE ord_no ='$orderNum'
I was then able to ouput it and save $row7['total'] to the variable $count.

PHP duplicate staffID

staff table
code
<?php
//db configuration
$q = "select * from staff";
$r = mysqli_query($dbc, $q);
$num_rows = mysqli_num_rows($r);
$staffID = array();
while($row = mysqli_fetch_array($r, MYSQLI_ASSOC))
{
$staffID[] = $row['staffID'];
}
for($i = 0; $i < $num_rows; $i++)
{
if($staffID[$i] == $staffID[$i+1])
{
$remark = "Not OK. Multiple staff ID selected.";
$i++;
}
else
{
$remark = "OK.";
}
$data[$i] = $staffID[$i].','.$remark.'<br />';
}
$list = array($data);
print_r($list);
?>
From above code, I want to check whether the staffID got duplicate.
Expected output
0001, OK.
0002, Not OK. Multiple staffID.
0003, OK.
0004, OK.
However, I get another error as below:
Undefined offset: 5 in play.php on line X.
How do I solve it?
By performing the correct query in the first place.
SELECT staffID
FROM staff
GROUP BY staffID
HAVING COUNT(staffID) > 1
Or if you need to know about all staff IDs:
SELECT staffID, COUNT(staffID) as qty
FROM staff
GROUP BY staffID
Just updating your code and i think you have to check the existence first :
if (isset($staffID[$i]) && isset($staffID[$i+!])) {
if($staffID[$i] == $staffID[$i+1])
{
$remark = "Not OK. Multiple staff ID selected.";
$i++;
}
else
{
$remark = "OK.";
}
$data[$i] = $staffID[$i].','.$remark.'<br />';
}
You get the error at this line:
if($staffID[$i] == $staffID[$i+1])
Say for example your $num_rows variable is 3. Then the $staffID array would have indexes 0, 1 and 2. But what happens at this line I noted is that once $i reaches 2 (which is a valid since it's less than 3) you go and do $i+1 which equals 3. And, as you can see, the index 3 is out of the bounds of the array.
If you wish to do this like you wrote your for loop should be like this:
for($i = 0; $i < $num_rows-1; $i++)
But, there is a better way without even doing the for loop. You can do it all in the while loop by making use of the in_array function. Or as Ignacio pointed out, you could do it all on the SQL level.
Not a good way to solve this problem. You should use GROUP BY query for this.
SELECT staffID, COUNT(staffID) as count
FROM staff
GROUP BY staffID
HAVING count > 1
And also about your error. It's because of
if($staffID[$i] == $staffID[$i+1])
on last iteration $i is equal 4 and $i+1 is 5. But $staffID array has no element with such key

End Foreach after X number of records PHP

I have the following query:
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 4");
while ($po = $trabajos->fetch_array()) {
$trab[] = $po;
}
This query is working fine, but, it shows only 4 records, but then again in another part of the same page I need the same table information but I don't want it to be limited, say I want 10 instead of only 4. so.
Section Header
Section Slider <-- here only shows 4 items as intended
Using a foreach as follow:
foreach ($trab as $it) {
// My html Code
}
Section Mid Body some info
Section Main Body More info
Section Mid End Footer <-- here I need the same information as in the slider section but with a different layout instead of only 4 items I need 10 items.
For that last item I have to open another query similar as before.
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 10");
while ($po = $trabajos->fetch_array()) {
$trab[] = $po;
}
So I was thinking is there a way to use:
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND()");
while ($po = $trabajos->fetch_array()) {
$trab[] = $po;
}
That query without the LIMIT and instead Limit the foreach to only fetch the first 4 rows or is there a way to use that query with the LIMIT but instead of 4 or 10, say I use 20, and for the first foreach only display the first 4 and for the second foreach show the rest after the first 4.
The main idea is not have more than 1 query for the same information.
this will exit a loop, but why not query 10 records, build your results, all 10 and then just output 4 of them, there and all 10 over yonder.
$x = 0;
foreach ($trab as $it) {
if($x == 5){
break; //will exit loop as will return.
}
// My html Code
++$x;
}
This will work with any kind of loop, you can also use continue to skip to the next pass of the loop
foreach ($trab as $it) {
if($x < 5){
continue; //code below here wont run until $x >= 5.
}
// My html Code
++$x;
}
i'm not sure to understand exactly what you want, but if you want to divide your array in 2 part. You can use a counter
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 20");
$i = 0;
$trab2 = new Array();
while ($po = $trabajos->fetch_array()) {
if($i < 4) {
$trab[] = $po;
} else {
$trab2[] = $po;
}
$i++;
}
First, RAND() is horrible since it essentially disables MySQL’s built in caching with each run of the query. But there is no best way for me to advise how to get around that based on your script’s requirements. So just keep that in mind. But here is what I would recommend.
That query without the LIMIT and instead Limit the foreach to only
fetch the first 4 rows or is there a way to use that query with the
LIMIT but instead of 4 or 10, say I use 20, and for the first
foreach only display the first 4 and for the second foreach show
the rest after the first 4.
Yes, just use array_slice like this:
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 20");
while ($po = $trabajos->fetch_array()) {
$trab[] = $po;
}
$trab_slice_1_size = 4;
$trab_slice_2_size = 10;
$trab_slice_1 = array_slice($trab, 0, $trab_slice_1_size);
$trab_slice_2 = array_slice($trab, $trab_slice_1_size, $trab_slice_2_size);
The nice thing about array_slice is you can cleanly select a start & end point. In my example I set the sizes in variables. Which makes it easier to adjust in your code if you somehow want to dynamically change values.
The easiest way is to use a counter variable:
function fetch_items($limit=10) {
public $trabajos,$trab;
$count=0;
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND()");
while (($po = $trabajos->fetch_array()) && ($count<$limit)) {
$count++;
$trab[] = $po;
}
}
If you call fetch_items() without a parameter, it defaults to 10 or less. If you specify a parameter it loads the array with up to the amount you specify. You could also have the function return the value of $count so you know how many were returned.
try;
$trabajos = $con->query("SELECT * FROM portafolio ORDER BY RAND() LIMIT 10");
$i = 0;
while ($i < 5 && $po = $trabajos->fetch_array()) {
.....
.....
$i++;
}
then, if you want to re-use the data,
mysql_data_seek($trabajos, 0);
$i = 0;
while ($i < 11 && $po = $trabajos->fetch_array()) {
.....
.....
$i++;
}

how to identify unsaved value from database using php mysql

I have to identify unsaved value from mysql table using php and mysql, for example i using table named as numtab and i have already stored some numbers 1, 3, 4, 7, 23, 12, 45 in numb column.
now i have generated one new number randomly(for example 23) and i have to check this number with already stored numbers,
if 23 is exist in the table mean i have to generate another one new number and have to check once again with stored values, this process have to continue till finding unsaved number.
if generated value is not exist in table mean can stop the process and can store this number in table.
here below the format i am currently using
$numb=23;
$qryb="select * from numtab where numb='$numb'";
$results=mysql_query($qryb)or die("ERROR!!");
if(mysql_num_rows($results) == 1)
{
$numb=rand(1,100);
mysql_query("insert query");
}
the problem is above the code is validation once only, its not verifying second time. i think if using for or while loop mean can solve this problem, but i dont know how to do looping, so help me to solve this problem.
You can use in clause like this :
$qryb="select * from numtab where numb in('$numb')";
$results=mysql_query($qryb)or die("ERROR!!");
$count = mysql_num_rows($results);
if ($count > 0) {
echo "number exist in db";
} else {
echo "number does not exist in db";
}
You could make a while() loop to check if the numbers exist in your database. You could also retrieve all numbers from the database, store them in an array and check if the generated number exists within that array.
The first option would be something like this:
do {
$numb=rand(1,100);
$qryb="select * from numtab where numb='$numb'";
$results = mysql_query($qryb) or die("ERROR!!");
} while(mysql_num_rows($results) >= 1)
mysql_query("insert query");
The second option would be something like this:
$query = mysql_query("SELECT DISTINCT(numb) as numb FROM numtab");
// set array
$array = array();
// look through query
while($row = mysql_fetch_assoc($query)){
// add each row returned into an array
$array[] = $row['numb'];
}
do
{
$numb = rand(1,100);
}
while(!in_array ( $numb , $array) ;
mysql_query("insert query");

php sql find and insert in empty slot

I have a game script thing set up, and when it creates a new character I want it to find an empty address for that players house.
The two relevant table fields it inserts are 'city' and 'number'. The 'city' is a random number out of 10, and the 'number' can be 1-250.
What it needs to do though is make sure there's not already an entry with the 2 random numbers it finds in the 'HOUSES' table, and if there is, then change the numbers. Repeat until it finds an 'address' not in use, then insert it.
I have a method set up to do this, but I know it's shoddy- there's probably some more logical and easier way. Any ideas?
UPDATE
Here's my current code:
$found = 0;
while ($found == 0) {
$num = (rand()%250)+1; $city = (rand()%10)+1;
$sql_result2 = mysql_query("SELECT * FROM houses WHERE city='$city' AND number='$num'", $db);
if (mysql_num_rows($sql_result2) == 0) { $found = 1; }
}
You can either do this in PHP as you do or by using a MySQL trigger.
If you stick to the PHP way, then instead of generating a number every time, do something like this
$found = 0;
$cityarr = array();
$numberarr = array();
//create the cityarr
for($i=1; $i<=10;$i++)
$cityarr[] = i;
//create the numberarr
for($i=1; $i<=250;$i++)
$numberarr[] = i;
//shuffle the arrays
shuffle($cityarr);
shuffle($numberarr);
//iterate until you find n unused one
foreach($cityarr as $city) {
foreach($numberarr as $num) {
$sql_result2 = mysql_query("SELECT * FROM houses
WHERE city='$city' AND number='$num'", $db);
if (mysql_num_rows($sql_result2) == 0) {
$found = 1;
break;
}
}
if($found) break;
}
this way you don't check the same value more than once, and you still check randomly.
But you should really consider fetching all your records before the loops, so you only have one query. That would also increase the performance a lot.
like
$taken = array();
for($i=1; $i<=10;$i++)
$taken[i] = array();
$records = mysql_query("SELECT * FROM houses", $db);
while($rec = mysql_fetch_assoc($records)) {
$taken[$rec['city']][] = $rec['number'];
}
for($i=1; $i<=10;$i++)
$cityarr[] = i;
for($i=1; $i<=250;$i++)
$numberarr[] = i;
foreach($cityarr as $city) {
foreach($numberarr as $num) {
if(in_array($num, $taken[]) {
$cityNotTaken = $city;
$numberNotTaken = $number;
$found = 1;
break;
}
}
if($found) break;
}
echo 'City ' . $cityNotTaken . ' number ' . $numberNotTaken . ' is not taken!';
I would go with this method :-)
Doing it the way you say can cause problems when there is only a couple (or even 1 left). It could take ages for the script to find an empty house.
What I recommend doing is insert all 2500 records in the database (combo 1-10 with 1-250) and mark with it if it's empty or not (or create a combo table with user <> house) and match it on that.
With MySQL you can select a random entry from the database witch is empty within no-time!
Because it's only 2500 records, you can do ORDER BY RAND() LIMIT 1 to get a random row. I don't recommend this when you have much more records.

Categories