PHP array logic - php

How can I set up an array of subjects with boolean values or test scores stored in them?
I am trying to display a gold medal if someone makes high scores on every test in a subject.
I wish I could be more clear in the framing of this question, but here is some code to help elucidate:
$resTestsQryStr = "SELECT TestID, Subject FROM Tests
WHERE " . $edstr . " AND " . $plstr . " AND " . $levelStr . " GROUP BY Subject";
$resTests = mysql_query($resTestsQryStr);
while ($rowT=mysql_fetch_array($resTests))
{
$subject=$rowT['Subject'];
$tID=$rowT['TestID'];
$resScore= mysql_query("SELECT Score FROM CompletedTests WHERE UserNum = '$userNum' AND TestID = '$tID'");
$rowScore= mysql_fetch_array($resScore);
if ($rowScore['Score'] < 100){
$medalWinArray[$subject]= false;
break;
}
else
$medalWinArray[$subject]= true;
}

I think this should do it:
SELECT Subject, MIN(Score) >= 100 GoldMedal
FROM Tests t
JOIN Completed Tests c ON c.TestID = t.TestID
WHERE $edstr AND $plstr AND $level
AND c.userNum = '$userNum'
GROUP BY Subject

Related

Find the average number for each user

First off, I am fairly new to coding. I try to do my due diligence before coming here for advice.
I am trying to write a function that will query the database for a users numbers and get the average for each user.
function getUserAverage($userID) {
//loop through user totals & calculate average for each user
$sql = "select p.userID, p.user, p.number ";
$sql .= "from " . DB_PREFIX . "numbers p ";
$sql .= "inner join " . DB_PREFIX . "users u on p.userID = u.userID ";
$sql .= "where u.userID = " . $user->userID . " ";
$sql .= "order by u.lastname, u.firstname";
$query = $mysqli->query($sql);
while ($row = $query->fetch_assoc()) {
//player average of numbers
$tba = ROUND(AVG(`number`),2);
}
$query->free;
return $tba;
}
The result I am hoping to get is something like:
user1 = 14.5
user2 = 35.8
user3 - 7.4
I have written code to get the average numbers for all, but the need is to get by individual user.
//Average Numbers
$sql_avgNum = "SELECT ROUND(AVG(`number`),2) AS `Average` \n"
. "FROM `" . DB_PREFIX . "numbers` \n";
$data = $mysqli->query($sql_avgNum);
$result_avgNum = mysqli_fetch_array($data);
echo ' <tr class="altrow"><td> Average Number: </td><td> ' .
$result_avgNum[0] . ' </td></tr>';
//End Average Numbers
for count average of individual data you must do it using group by. Further reference of group by is here:
I'm not very sure, but I think that this is what you're looking for:
function getUserAverage($userID) {
// loop through user totals & calculate average for each user
$sql = "SELECT p.userID, u.user, AVG(p.number) AS 'avarage' ";
$sql .= "FROM " . DB_PREFIX . "numbers p ";
$sql .= "INNER JOIN " . DB_PREFIX . "users u ON(p.userID = u.userID) ";
$sql .= "WHERE p.userID = " . $user->userID . " ";
$sql .= "GROUP BY p.userID ";
$sql .= "ORDER BY u.lastname, u.firstname";
$query = $mysqli->query($sql);
while ($row = $query->fetch_assoc()) {
//player average of numbers
$tba = $row['avarage'];
}
$query->free;
return $tba;
}

Remaining two rows get skipped in for-loop

I am programming a maintenaince thing for tournaments. Players are divided into "leagues". At the end, the first player of league x gets to play against the losers of league y. Winner of league y meets loser of league z etc. Then this rule gets repeated fot the numbers 2 and second lasts of the next league, 3rds and 3rd lasts of next league and so on. The number of leagues varies every time. Everything works really fine until it comes to the last two remaining players, let's say the middle player of league x don't get connected to the middle player of league y.
I found a way to work around this glitch but I'd rather have it working like it should.
This is my code: (khzz is the total amount of players without regarding leagues). Anybody sees what's wrong? Thanks!
for ($doen=0; $doen<=$hkzz; $doen++) {
$unid2 = "" . $doen . "-" . rand(1600,20000) . "";
$koppelpak = $conn->query ("SELECT * FROM poules WHERE poule='$startmet' AND amsyst='' ORDER BY ABS(ptn) DESC, karma DESC LIMIT 1");
//$kppk = mysqli_fetch_assoc($koppelpak);
while ($kppk = $koppelpak->fetch_array()) {
$conn->query("UPDATE poules SET amsyst='$unid2' WHERE koppel='$kppk[koppel]' ") or die(mysqli_error($conn));
echo "koppel " . $kppk['koppel'] . " uit poule " . $startmet . " tegen ";
$koppelpak2 = $conn->query ("SELECT * FROM poules WHERE poule='$volgende' AND amsyst='' ORDER BY ABS(ptn) ASC, karma ASC LIMIT 1");
while ($kppk2 = $koppelpak2->fetch_array()) {
$conn->query("UPDATE poules SET amsyst='$unid2' WHERE koppel='$kppk2[koppel]' ") or die(mysqli_error($conn));
echo "koppel " . $kppk2['koppel'] . " uit poule " . $volgende . "<br />";
}
$startmet = $startmet + 1;
$werk = $werk + 1;
if ($startmet>$hoep) { $startmet="1"; }
$volgende = $volgende + 1;
if ($volgende>$hoep) { $volgende="1"; }
//$volgen = $volgen + 1;
} // while
} // for

Can you use php with an SQL case?

I am trying to optimize some of my code and i believe i need an if/else or case to do this, however I think i would need php in the query to get it to work
here is the code I am trying to optimize
$sql = "SELECT value, COUNT(*) AS count
FROM sodsurvey LEFT OUTER JOIN age
ON sodsurvey.age_id = age.id
WHERE value IS NOT NULL AND office_id = " . $office_id . "
GROUP BY age_id; ";
if ($_SESSION['filteryear'] != 0 && $_SESSION['filtermonth'] != 0) {
$sql = "SELECT value, COUNT(*) AS count
FROM sodsurvey LEFT OUTER JOIN age
ON sodsurvey.age_id = age.id
WHERE value IS NOT NULL AND office_id = " . $office_id . "
AND year = " . $_SESSION['filteryear'] . " AND month = " . $_SESSION['filtermonth'] . "
GROUP BY age_id; ";
} else if ($_SESSION['filteryear'] != 0 || $_SESSION['filtermonth'] != 0) {
$sql = "SELECT value, COUNT(*) AS count
FROM sodsurvey LEFT OUTER JOIN age
ON sodsurvey.age_id = age.id
WHERE value IS NOT NULL AND office_id = " . $office_id . "
AND (year = " . $_SESSION['filteryear'] . " OR month = " . $_SESSION['filtermonth'] . ")
GROUP BY age_id; ";
}
and this is what I have tried to give you a rough idea of what I am trying to achieve
$filter = "";
if ($_SESSION['filteryear'] != 0 && $_SESSION['filtermonth'] != 0) {
$filter = "AND year = " . $_SESSION['filteryear'] . " AND month = " . $_SESSION['filtermonth'] . ""
} else if ($_SESSION['filteryear'] != 0 || $_SESSION['filtermonth'] != 0) {
$filter = "AND (year = " . $_SESSION['filteryear'] . " OR month = " . $_SESSION['filtermonth'] . ")"
}
$sql = "SELECT value, COUNT(*) AS count
FROM sodsurvey LEFT OUTER JOIN age
ON sodsurvey.age_id = age.id
WHERE value IS NOT NULL AND office_id = " . $office_id . "
CASE
WHEN ".isset($filter)." THEN ". $filter ."
END
GROUP BY age_id; ";
You can build up an array of filters depending on which values (year, month, etc) are set, and then combine them all into the WHERE clause. You don't need to worry about all the separate cases where both are set, or one are set, and so on.
I would also strongly echo the advice above that recommended looking into prepared statements, but this will hopefully get you on your way.
<?php
$office_id = 10;
$_SESSION['filteryear'] = 2016;
$_SESSION['filtermonth'] = 12;
$filters = [
"value IS NOT NULL",
"office_id = {$office_id}",
];
if ($_SESSION['filteryear']) {
$filters[] = "year = {$_SESSION['filteryear']}";
}
if ($_SESSION['filtermonth']) {
$filters[] = "month = {$_SESSION['filtermonth']}";
}
$sql = "
SELECT value, COUNT(*) AS count
FROM sodsurvey
LEFT JOIN age ON sodsurvey.age_id = age.id
WHERE " . implode(' AND ', $filters) . "
GROUP BY age_id;
";
The implode line combines each filter that's been set into a single WHERE clause.
is it valid to use PHP with a case in my attempt above?
No. PHP code cannot be part of your SQL query, however your PHP code can generate SQL query
In MySQL, I am trying to find a way to optimize my code
Just make your SQL code generated by PHP code based on all the conditions. You can easily concatenate strings being partions of your query conditionally.

PHP/MySQL different value for each row

I've searched and I've tried many different things but I haven't been able to come up with anything to work the way I want. What I have is a direct message system but I want to show next to the users name how many new messages they have from that person if it's more than 0. Everything I've tried just shows one value for all of the conversations. In my database I have a column that is if the user who received the message read it, if they had it turns the 'no' into a 'yes', otherwise it shows 'no'.
Thanks in advance for your help!
EDIT:
One thing for my database...Only the first message in the conversation has both the to_id and from_id after that all the other messages in the conversation only has the from_id. So what I'm trying to do is count how many where the from_id is not your user_id, so the non-signed in user user_id. If that makes sense.
Here is my code accessing the database:
// Get the conversations
$get_conversations = "SELECT dm.convo_id, dm.message_id, dm.to_id, dm.from_id, dm.user2read, u.name, u.user_id" .
" FROM users u" .
" JOIN direct_messages dm" .
" ON dm.from_id = u.user_id" .
" OR dm.to_id = u.user_id" .
" WHERE u.user_id = " . $_SESSION['user_id'];
" GROUP BY dm.convo_id" .
" LIMIT 1";
// Run the conversation query
$convo_result = mysql_query($get_conversations);
And then some HTML code
And more php in the body tags
<?php
while ($teg = mysql_fetch_array($convo_result)) {
if($teg) {
$to_id2 = $teg['to_id'];
$from_id2 = $teg['from_id'];
if($from_id2 == $_SESSION['user_id']) {
$id_of_other_person = $to_id2;
} else if($from_id2 != $_SESSION['user_id']) {
$id_of_other_person = $from_id2;
}
// Get the name of the other person
$get_other_name = "SELECT name FROM users WHERE user_id = " . $id_of_other_person;
// Run the query on the other person's name
$query_name = mysql_query($get_other_name);
if($query_name) {
$yelp = mysql_fetch_array($query_name);
$name_of_other_person = $yelp['name'];
}
$get_user2read = "SELECT dm.convo_id, dm.message_id, dm.to_id, dm.from_id, dm.user2read, u.name, u.user_id" .
" FROM users u" .
" JOIN direct_messages dm" .
" ON dm.from_id = u.user_id" .
" OR dm.to_id = u.user_id" .
" WHERE u.user_id = " . $_SESSION['user_id'];
" AND user2read = 'no'" .
" GROUP BY dm.convo_id" .
" LIMIT 1";
$query_user2read = mysql_query($get_user2read);
$alg = mysql_fetch_array($query_user2read);
?>
<?php if(COUNT($alg['user2read']) > 0 && $alg['user2read'] == 'no') : ?>
<h3>You have <?php echo COUNT($teg['user2read']); ?> new messages - from <?php echo $name_of_other_person; ?></h3>
<?php else : ?>
<?php endif; ?>
<?php
}
}
?>
I would post in image of my direct_messages table but I don't have enough reputation...
Here is a diagram of my table:
Field Type Collation Attributes Null Default Extra Action
convo_id bigint(20) No
message_id int(11) No
to_id int(11) No
from_id int(11) No
message varchar(5000) latin1_swedish_ci No
timestamp timestamp No CURRENT_TIMESTAMP
user1read varchar(3) latin1_swedish_ci No
user2read varchar(3) latin1_swedish_ci No
EDITED: I erased the backslashes
This is not correct:
<h3>You have <?php echo COUNT($teg['user2read']); ?> new messages - from <?php echo $name_of_other_person; ?></h3>
count() is used for arrays, but the elements of $teg are just the column values from the table. If you want to count records grouped by a column, you need to use the MySQL COUNT() function in your query. Or in this case, since you only want to count messages that fit a specific criteria, use SUM():
$get_conversations = "SELECT dm.convo_id, dm.message_id, dm.to_id, dm.from_id, u.name, u.user_id, SUM(dm.user2read = 'no') unread_count" .
" FROM users u" .
" JOIN direct_messages dm" .
" ON dm.from_id = u.user_id" .
" OR dm.to_id = u.user_id" .
" WHERE u.user_id = " . $_SESSION['user_id'] .
" AND dm.user2read = 'no' " .
" GROUP BY dm.convo_id" .
" LIMIT 1";
Then you can use $teg['unread_count'] to get the count of unread messages in that conversation.
I don't think you need the inner query $get_user2read. All the information is in $get_conversations now. It was wrong, because it wasn't getting the row specific to the conversation in that iteration of the loop.
This
$yelp = mysql_fetch_array($query_name);
$name_of_other_person = $yelp\['name'\];
looks wrong.
You need to loop the $yelp like you did $teg.

Can't get score to update with this mysql statement

I'm guessing that I'm just a little rusty or something because it seems like this should be working. Am I missing something here...
Here is the code I am trying to use...
<?php
echo dbConn();
$existing_time = mysql_result(mysql_query("SELECT p_time FROM scores WHERE p_uid=$uid"), 0);
$existing_category = mysql_result(mysql_query("SELECT p_cat FROM scores WHERE p_uid=$uid AND p_cat=$pieces"), 0);
if ($existing_category == "") {
mysql_query(
"INSERT INTO scores VALUES (
'',
'$uid',
'$pusername',
'$time',
'$pieces'
)");
} elseif ($existing_time <= $time) {
echo "No Change! Old Score Was Better (Lower)";
} elseif ($existing_time > $time) {
mysql_query("UPDATE scores SET p_time = " . $time . " WHERE p_uid = " . $uid . " AND p_cat = " . $pieces . "");
};
?>
Now... Here is what I am trying to do...
I am collecting info from the database where the users username AND category match. If the category for that user does not exist, it inserts the latest score. (This much works.)
Then, if the category does exist but the old score is better, it just does nothing. (This part works too)...
However, what I can't seem to do is get it to update the last score, if the current score is better (lower score, since this is a time based game.) It doesn't update the score.
I am trying it this way: By updating a row in "scores" where the USERNAME and the CATEGORY match at the same time.
Please note... where it says "pieces". this is a category. Where it says "time", this is a score. The score is returned as 00:00:00 for hours minutes and seconds.
EXAMPLE: (in parentheses is the database row name)
id (ID) = just KEY id in sequencial order
user id (p_uid) = 123456789
username (p_username) = somename
score (p_time) = 00:01:03
category (p_cat) = 10
Change you update statement to:
mysql_query("UPDATE scores SET p_time = '" . $time . "' WHERE p_uid = " . $uid . " AND p_cat = " . $pieces . "");
You have missed quotes in the update statement around $time.

Categories