Taking mean of all students for one subject using php - php

I have an SQL table of students with one subject. I would like to take the mean of all the students for this particular subject such that:
Sum of the subject/Number of total students
The table looks like this:
Student ID : 1
=============
Maths : 40
Student ID : 2
=============
Maths : 60
Student ID : 3
=============
Maths : 90
Student ID : 4
=============
Maths : 0
So if the student has scored 0, then ignore this student and its score in calculating the mean.
<?php
if(!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true){
header("location: login.php");
exit;
}
$db = new PDO("mysql:host=localhost; dbname=db;charset=utf8",'user','');
$sql = "SELECT * FROM Students";
$stmt = $db->query($sql);
while($data = $stmt->fetch(PDO::FETCH_OBJ)){
//How to take the mean of 1 subject for all students?
}
?>

Fix this line first so that...you can only get scores greater that 0
$sql = "SELECT * FROM students WHERE subjectscore > 0"; //assuming your column for scores is "subjectscore"
The the rest of the code to get mean should be
$stmt = $db->query($sql);
while($data = $stmt->fetch(PDO::FETCH_OBJ)){
$sumparts .= $data->subjectscore."+"; //Add a delimiter after every returned obj
}
print_r($sumparts); //For debug :to see which ones are selected
$sumarr = explode("+",$sumparts); // Convert the delimited string to array
$sum = array_sum($sumarr); //Get sum of values of array in this case the scores
$divisor = count($sumarr) - 1; //The minus 1 is necessary since well the delimited string will always have 1 extra key therefore making the count to count 1 more unnnecessary key
$total = $sum/$divisor; //Sum of all divided by the total number of objects
echo $total;

Related

how to convert multiple row data into array and subtract it from another array?

I am fetching multiple rows from my data base like,
$query = "SELECT * FROM student_info where district = '".$admdistrict."' AND user_status = 'approved' ORDER BY id DESC";
$result = mysql_query($query) or die(mysql_error());
$delete = mysql_fetch_array($resultt);
$std_delete_array = explode(',', $delete['id']);
the value of id in database is like 4,5,6 in different rows but it is giving only first value 4.
Another array I am fetching is,
$query="SELECT * FROM events where id='$district'";
$showdata=mysql_query($query) or die(mysql_error());
$user=mysql_fetch_array($showdata);
$std_fulllist_array = explode(',', $user['std_list']);
the value in database is 4,5,6,8. But in single coloumn, so it is giving proper output. now I want to subtract $std_delete_array from $std_fulllist_array.
I am using following code,
$values = array_diff($std_fulllist_array, $std_delete_array);
which is only subtracting first value of $std_delete array.
strucutre of table student_info is
id ! name ! District
4 a panipat
5 b panipat
6 c panipat
strucutre of table events is
id ! district ! std_list
1 panipat 4,5,6
2 karnal 4,7,8
3 chandigarh 5,6,7
You are saying the value of id in database is like 4,5,6 in different rows
that means your table is look like
id district
-- ---------
4 abc
5 def
6 geh
8 ijk
so your first query is fetching multiple records.
EDIT
So your query would be
$ret_ = array();
$query = "SELECT * FROM student_info where district = '".$admdistrict."' AND user_status = 'approved' ORDER BY id DESC";
$result = mysql_query($query) or die(mysql_error());
if (mysql_num_rows($result) > 0) {
// output data of each row
while($row = mysql_fetch_array($result)) {
echo $row['id'];
$ret_[] = $row;
}
}
print_r($ret_);

Increasing column number value based on another column

I have a table code with the following table structure. id is auto incrementing id, the code is a random unique 15 digit code and customer_id is the customer's id.
id code customer_id
1 123...4 1
2 124...5 1
3 128...3 1
4 234...1 2
5 678...3 2
6 567...8 1
The code is actually a 15 digit number which I am generating randomly as per below code. Based on the user input for the number of codes I generate the codes at once, insert ignore into the table and count post addition to the table if few lines were ignored due to duplicates and add the additional ones needed to make the total count needed by the user. I use this approach because the request for the number of codes is usually around 50k to 100k and this approach works well.
do{
$codes = array();
$question_marks = array();
$sql = "SELECT count(*) FROM code";
$stmt = $this->db->prepare($sql);
$stmt->execute();
$initialCount = $stmt->fetchColumn();
for ($i=0;$i<$codesToGenerate;$i++){
$code = getToken(15);
array_push($codesArray, $code, $customerId);
$question_marks[] = '(' . placeholders('?', 2) . ')';
}
$datafields = "code, customer_id";
$this->db->beginTransaction(); // also helps speed up your inserts.
$sql = "INSERT IGNORE INTO code (" . $datafields . ") VALUES " . implode(',', $question_marks) ;
$stmt = $this->db->prepare($sql);
try {
$stmt->execute($codesArray);
}catch (\PDOException $e){
echo $e->getMessage();
$result = 0;
}
$this->db->commit();
$sql = "SELECT count(*) FROM code";
$stmt = $this->db->prepare($sql);
$stmt->execute();
$finalCount = $stmt->fetchColumn();
$rowsInserted = $finalCount - $initialCount;
$codesGenerated += $rowsInserted;
$codesToGenerate = $codesToGenerate - $rowsInserted;
}while($codesToGenerate>0);
I have added a column serial_number in table and I want to add a serial_number which will increment for each value of respective customer like below based on the customer_id. How do I change PHP code to add serial_number as well. Please note that I want to avoid holes in serial_number.
id code customer_id serial_number
1 123...4 1 1
2 124...5 1 2
3 128...3 1 3
4 234...1 2 1
5 678...3 2 2
6 567...8 1 4
How do I do this?
Below are some of my thoughts:
1)Should it be done seperately post this transaction?
2)Should I maintain a last count of serial_number for each customer in a separate table and then increment in PHP before adding to table.
3) How do I take care of concurrencies if I use the approach mentioned in 2 above

PhP/MySQL: how to dynamically change my (large and always changing) database

Scenario
I have a MySQL database with 10.000 rows. Setup of the database:
ID UniqueKey Name Url Score ItemValue
1 5Zvr3 Google google.com 13 X
2 46cfG Radio radio.com -20 X
3 2fg64 Yahoo yahoo.com 5 X
.... etc etc etc
As you can see, each item has a score. The score is constantly changing. Google may have a score of 13 now, but tomorrow it may be 80, or -50.
What I want:
I want to create a system that creates a hierarchy in my current database, based on the score of the items. Right now I'm thinking about percentile ranks, meaning that the highest scoring items will be close to 100%, and the lowest scoring items will be close to 0%. For this I created some code that will try to achieve what is shown here: http://www.psychstat.missouristate.edu/introbook/sbk14m.htm
This is my code:
$sql = "SELECT * FROM database order by Score";
$result = $conn->query($sql);
$count = 0;
while ($row = $result->fetch_assoc()) {
$woow = $row['Score'];
$sql = "SELECT * FROM database WHERE Score = $woow";
$resultnew = $conn->query($sql);
$somanythesame = $resultnew->num_rows;
$itemPercentile = ( ($count/$result->num_rows + 0.5*$somanythesame/$result->num_rows) * 100 );
$rowID = $row['ID'];
$sql2 = "UPDATE database SET itemValue = $itemPercentile WHERE ID = $rowID";
$conn->query($sql2);
$count++;
}
This works, but for one problem it does not: There are many items in my database, many with the same score. To illustrate my problem, here is a very simple 10-row database with only the Scores:
Scores
-10
0
0
0
10
20
20
30
40
50
The problem with my code is that it doesn't give the same percentile for the items with the same Score, because it takes in account all previous rows for the calculation, including the ones with the same Score.
So, for the 2nd, 3rd and 4th item with a Score of 0, it should be like this: (1/10 + 0.5*1/10) * 100. Problem is, that for the 3rd item it will do (2/10 + 0.5*1/10) * 100 and the 4th item it will do (3/10 + 0.5*1/10) * 100.
Then, for the 5th item with a score of 10, it should do (4/10 + 0.5*1/10) * 100. This is going well; only not for the items with te same score.
I'm not sure if I explained this well, I find it hard to put my problem in the right words. If you have any questions, let me know! Thank you for your time :)
You need to maintain an "identical count" ($icount) variable that tracks the number of items with an identical score and a "current score" ($score) that tracks the current score.
$icount = 0;
$score = null;
Increment $icount instead of $count when $woow == $score (identical value check). Otherwise, add it to your $count and increment, and then reset the $icount value to 0.
if ($woow == $score) {
$icount++;
} else {
$count += $icount + 1;
$icount = 0;
}
Finally, set your $score value to the latest $woow for testing in the next iteration of the loop:
$score = $woow;
This will allow items with the same Score to have the same $count value, while incrementing an additional $icount times when a new $score is found.
Your final code will look like this:
$sql = "SELECT * FROM database order by Score";
$result = $conn->query($sql);
$count = 0;
$icount = 0;
$score = null;
while ($row = $result->fetch_assoc()) {
$woow = $row['Score'];
$sql = "SELECT * FROM database WHERE Score = $woow";
$resultnew = $conn->query($sql);
$somanythesame = $resultnew->num_rows;
$itemPercentile = ( ($count/$result->num_rows + 0.5*$somanythesame/$result->num_rows) * 100 );
$rowID = $row['ID'];
$sql2 = "UPDATE database SET itemValue = $itemPercentile WHERE ID = $rowID";
$conn->query($sql2);
if ($woow == $score) {
$icount++;
} else {
$count += $icount + 1;
$icount = 0;
}
$score = $woow;
}
You can change $sql query:
$sql = "SELECT *,count(*) FROM database group by Score order by Score";
In this case, you fetch score with counts and no more select needed in the while loop.
Even you can select Percentile in MySQL query:
Select t2.* , #fb as N , ((t2.fb1 + 0.5 * t2.fw)/#fb*100) as percentile from (
Select t1.* , (#fb := #fb + t1.fw) as fb1 from (
Select score,count(*) as fw From tablename group by score order by score ASC
) as t1
) as t2
I think this query returns most of columns which you may needs to check results.

MySQL Count in PHP while loop only returns one result then Null

Ok, so I have some MySQL tables as follows:
Buildings
Building-ID Building-Name
===========----=============
1 Building-1
2 Building-2
3 Building-3
4 Building-4
Building-1
Mroom State
=====----======
1 Booked
2 Empty
3 Empty
4 Empty
Building-2
Mroom State
=====----======
1 Booked
2 Empty
3 Empty
4 Empty
And a query in PHP as follows (Ignore the hard coded while, I've simplified the code a bit):
$sql = "select * from Buildings";
$result = mysql_query ($sql) or die(mysql_error());
while ($row = mysql_fetch_array($result))
{
$building[] = $row['ward_name'];
}
$v1 = 0;
while ($v1 < 4)
{
$sql = "SELECT COUNT(*) FROM `$building[$v1]` WHERE state = 'Empty'";
$result = mysql_query($sql) or die(mysql_error());
$count = mysql_result($result, 00);
var_dump($count[$v1]);
$v1 = $v1 + 1;
}
To my way of thinking this should create an array of the buildings contained in the "Buildings" table, start a loop, load the building name from the array and provide a row count for the table of how many rows contain "Empty" in the state column. What it actually does is provide a count for the first table and then provides "NULL" for the rest.
I'd appreciate any help you can give me.
Cheers!
What about changing your data model?
Table buldings can be kept as is:
Buildings
Building-ID Building-Name
===========----=============
1 Building-1
2 Building-2
3 Building-3
4 Building-4
New table:
Rooms
Building-ID Mroom State
===========-=====-=====
1 1 1
1 2 0
2 1 0
State 0 = Empty, State 1 = Booked
Then use a join with group by:
select count(*) from buildings b inner join rooms r on r.bid = b.id where r.state = 0 group by b.id;
Then you will get a row for each building with the count of empty rooms. You won't need a table for each building.
This does noit make sense:
$count = mysql_result($result, 00);
var_dump($count[$v1]);
you mean to write:
$count[$v1] = mysql_result($result, 00);
var_dump($count[$v1]);
Also do not use several tables with names matching columns of other tables.
You can use one table with a primary key that spans two columns instead, for example create primary key on($buildingid,$roomid)
so that the table has columns $buildingid,$roomid, and $state.
mysql_result() returns a string, not an array.
Modify the code and check that now it works as expected.
var_dump($count);

Php lottery issues multi winner problems

I have created a lottery script in php. My problem is now selecting more then one winner. Because it is possible for players to have the same number on their tickets. Here I am supplying the two table structures and the source code.
lotto_game {
id(int)
jackpot(int)
status(varchar10)
pick_1(int)
pick_2(int)
pick_3(int)
pick_4(int)
pick_5(int)
tickets_sold(int)
winner(text)
}
lotto_picks {
lotto_id(int)
user_id(int)
choice_1(int)
choice_2(int)
choice_3(int)
choice_4(int)
choice_5(int)
ticket_status(int)
}
These are my two tables with in my database. For examples sake we will create 2 users with the id's 1, and 2. So what happens is when the script runs it is suppose to change the lotto_game status from 'active' to 'finished' then add the random lottery numbers into each pick_* column.
$one = rand(1,30);
$two = rand(1,30);
$three = rand(1,30);
$four = rand(1,30);
$five = rand(1,30);
mysql_query("UPDATE `lotto_game` SET
pick_1 = '$one',
pick_2 = '$two',
pick_3 = '$three',
pick_4 = '$four',
pick_5 = '$five',
status = 'finished'
WHERE status = 'active'");
That wasn't too hard I will admit. But this is just the beginning of the end.
$lotto['tickets'] = mysql_query("SELECT ticket_id FROM `lotto_picks` WHERE ticket_status='valid'");
#$lotto[winners] = mysql_query("SELECT ticket_id,user_id FROM `lotto_picks` WHERE choice_1 = '$one' AND choice_2 = '$two' AND choice_3 = '$three' AND choice_4 = '$four' AND choice_5 = '$five'");
$lotto['num_tickets'] = mysql_num_rows($lotto['tickets']);
#$lotto[winner_id] = mysql_fetch_array(#$lotto[winners]);
$lotto['jackpot'] = mysql_query("SELECT jackpot FROM `lotto_game` WHERE status='active'");
$lotto['winner_jackpot'] = mysql_fetch_array($lotto['jackpot']);
$lotto['num_winners'] = mysql_num_rows($lotto['winners']);
//echo #$lotto['num_tickets'];
//echo #$lotto['num_winners'];
$winner = $lotto['num_winners'];
//echo #$lotto['winner_id']['user_id'];
$jackpot = $lotto['winner_jackpot']['jackpot'];
$id = #$lotto[winner_id][user_id];
if ($winner == 1) {
mysql_query("UPDATE `character` SET
decivers = decivers +'$jackpot'
WHERE user_id='$id'");
}
This is what I have come up with and it really seems to work with one winner. But I just cant figure out where to go from here. I have tried using some arrays but nothing works. I know what needs to be done but can't figure out how to do it.
When I search for winners I need to put into an array all their user id's.
so extra decivers is money, if anyone is confused on that. The status on the tickets doesn't really matter here but if you must know it just determines if the ticket_status is 'valid' or 'invalid'
i think you've chosen the wrong storage formats for your picked numbers. The standard approach is to use binary values which have N-th bit set if the number N is choosen.
Consider this example: user chooses numbers "2 4 5 9 11". Setting corresponding bits to 1 gives '10100011010' which is decimal 1306. Now the lottery picks "4 7 9 12 13" which is '1100101001000' == 6472. Perform a bitwise AND on both values and count the number of bits set in the result:
SELECT BIT_COUNT(1306 & 6472)
this immediately tells us that the user has 2 correct picks. Just as easy you can select "full" winners:
SELECT * FROM tickets WHERE BIT_COUNT(tickets.pick & lotto.pick) = 5
or sort the tickets by the number of correct picks
SELECT * FROM tickets ORDER BY BIT_COUNT(tickets.pick & lotto.pick) DESC
$winners_array = array();
if(mysql_num_rows($lotto['winners'])!=0){
while($row =mysql_fetch_array($lotto['winners'])){
if(!in_array($row['user_id'],$winners)) $winners[] = $row['user_id'];
}
}
$winners will be an array with all the winners user_ids

Categories