Moving from mysql to mysqli - problems - php

I have the following code:
$query3 = "SELECT
Office,
COUNT(Office) As Tot_Part,
(SELECT COUNT(Office) FROM trespondent WHERE completion_status= 'Started' OR completion_status = 'Complete') As Total_Resp
FROM trespondent
WHERE completion_status <> 'New'
GROUP BY Office
ORDER BY Office";
$result3 = $mysqli->query($query3);
I am trying to move from mysql to mysqli and am struggling terribly. The above statement brings back only 1 row and not the 26 that there should be. Any pointers welcome.

That's because you're fetching just one row ($los = $result3->fetch_row();).
Try it in a loop.
Like this:
$result3 = $mysqli->query($query3);
while($los = $result3->fetch_row()) {
print_r($los); /* sanity */
}

Related

Guidance with a SQL query - results duplicating

Really need some guidance, I have a website where people can upload images to competitions and they get a result (marks), I want to pull out a LEADERSHIP BOARD to see how everyone is doing. However the SQL Query I have has people names duplicated, could someone tell me where to alter my query so the results for say 1 person entering 3 competitions are added up, and only the TOTAL marks are stated once in the output. The results are kept in tblMembEntComp fldResult.
What I'm currently getting:
My PHP Code:
<p><b>LEADERSHIP BOARD</b></p>
<?php
$query = "SELECT `tblMember`.`fldFName`, `tblMember`.`fldSName`, `tblMembEntComp`.`fldResult` FROM `tblMember` AS `tblMember` JOIN `tblMembEntComp` as `tblMembEntComp` ON `tblMember`.`fldMemberID` = `tblMembEntComp`.`fldMemberID`ORDER BY `fldResult` DESC";
$result = $conn -> query($query);
while($row = $result -> fetch_assoc())
{
echo $row['fldFName']." ".$row['fldSName']." ".$row['fldResult']."<br>";
}
?>
UPDATE:
I have tried the GROUP BY function as suggested by user below however I am getting thrown the error:
You seem to want an aggregation query. Something like:
SELECT m.fldSName, SUM(mec.fldResult) as fldResult
FROM tblMember m JOIN
tblMembEntComp mec
ON m.fldMemberID =mec.fldMemberID
GROUP BY m.fldSName
ORDER BY SUM(mec.fldResult) DESC
You should group by query by tblMember primary key as below:
<?php
$query = "SELECT `tblMember`.`fldFName`, `tblMember`.`fldSName`, `tblMembEntComp`.`fldResult`, `tblMember`.`fldId` FROM `tblMember` AS `tblMember` JOIN `tblMembEntComp` as `tblMembEntComp` ON `tblMember`.`fldMemberID` = `tblMembEntComp`.`fldMemberID` GROUP BY `tblMember`.`fldId` ORDER BY `fldResult` DESC";
$result = $conn -> query($query);
while($row = $result -> fetch_assoc())
{
echo $row['fldFName']." ".$row['fldSName']." ".$row['fldResult']."<br>";
}
?>
You can update group by field as your primary key. Hope it helps you :)

sql inserting twice

Hello i have a sql statement that ranks my records and inserts the ranks into a database.
The problem i am having is that when i run the script. It deletes the old rankings. And inserts the new rankings fine, but it inserts every ranking twice. So there will be 2 rank 1's, 2 rank 2's, ect ect.
The kicker to my problem, is if i delete all the records in phpmyadmin. Then run the script. It doesnt make duplicates.
I tried just letting the script delete, to debug if the delete script is working, and it deleted all the rows fine. Hence im really confused :(
if you could look at my code and give me some insight that'd be awesome. Thank you
<?php
// Connect to the database we want to insert/update
$Server_Location = "localhost";
$Server_User_Name = "x";
$Server_Password = "y";
$Database_Name = "z";
// Create connection
$Conn_Info = mysqli_connect($Server_Location, $Server_User_Name, $Server_Password, $Database_Name);
// Check connection
if ($Conn_Info->connect_error) {
die("Connection failed: " . $Conn_Info->connect_error);
}
if($_GET['Password'] != 'q'){
die();
}
$Sql_Delete_Duplicate = "DELETE FROM ranks";
if ($Conn_Info->query($Sql_Delete_Duplicate) === TRUE) {
echo "User Deleted";
}
else {
echo "Error User Not Deleted";
echo $Conn_Info->error;
}
// Overall Games - Rankings (1000)
$Top_1000_Sql = "Select games, overall_games_user.ID as UserID, Name FROM overall_games, overall_games_user WHERE overall_games.User_ID = overall_games_user.ID AND DATE(Date_Updated) = DATE(NOW()) GROUP BY User_ID ORDER BY Games DESC LIMIT 10000";
$Top_1000_Results = $Conn_Info->query($Top_1000_Sql);
$rank = 0;
if ($Top_1000_Results->num_rows > 0) {
echo $Top_1000_Results->num_rows;
while($Top_Player = $Top_1000_Results->fetch_assoc()) {
$rank += 1;
$User_ID = $Top_Player["UserID"];
$Games_Played = $Top_Player["games"];
$Insert_Top_Player_Sql = "INSERT INTO ranks (Rank_Type,Rank, User_ID, games)
VALUES ('Total', {$rank}, {$User_ID}, {$Games_Played})";
if ($Conn_Info->query($Insert_Top_Player_Sql) === TRUE) {
echo $rank . "-";
}
else {
echo "Error User Not Added";
echo $Conn_Info->error;
}
}
}
// Yesterday Games - Rankings
// Graph Stats
/*
SELECT AVG(Games) FROM overall_games WHERE DATE(Date_Updated) = DATE(NOW()) AND User_ID IN (SELECT ID FROM overall_games_user WHERE division LIKE('%BRONZE%'));
SELECT AVG(Games) FROM overall_games WHERE DATE(Date_Updated) = DATE(NOW()) AND User_ID IN (SELECT ID FROM overall_games_user WHERE division LIKE('%SILVER%'));
SELECT AVG(Games) FROM overall_games WHERE DATE(Date_Updated) = DATE(NOW()) AND User_ID IN (SELECT ID FROM overall_games_user WHERE division LIKE('%GOLD%'));
SELECT AVG(Games) FROM overall_games WHERE DATE(Date_Updated) = DATE(NOW()) AND User_ID IN (SELECT ID FROM overall_games_user WHERE division LIKE('%PLATINUM%'));
SELECT AVG(Games) FROM overall_games WHERE DATE(Date_Updated) = DATE(NOW()) AND User_ID IN (SELECT ID FROM overall_games_user WHERE division LIKE('%DIAMOND%'));
*/
?>
You are using Group By without aggregate function so change your query to:
$Top_1000_Sql = "Select Count(games) as gameCount, overall_games_user.ID as UserID, Name FROM overall_games, overall_games_user WHERE overall_games.User_ID = overall_games_user.ID AND DATE(Date_Updated) = DATE(NOW()) GROUP BY UserID ORDER BY Games DESC LIMIT 10000";
Also note change in GROUP BY UserID in above SQL
In $Games_Played variable fetch value of count:
$Games_Played = $Top_Player["gameCount"];
Try Changing VALUES to VALUE in your query.
Also it sometimes so happens that you have an .htaccess to point every thing to the index file. Naturally the browser will request the script twice, once for the script it self, the other is for the favicon.
The fix is to Try to edit the .htaccess to prevent redirection to the index file when the browser is requesting for favicon.ico
Try these two things. I hope it would solve your problem :) Else let me know again.

How does one go about deleting records from an array with Joins

I have a query with multiple joins in it. After I take the results and run it through a Id-checker I want to be able to delete records from that array where the IDDestination equals $ID.
Since this query has joins on it and I am filtering them based on one of the joined tables, How do I go about deleting those records from the array based off that joined table?
And I only wanted this to happen after the user confirms.
$query = "
select d.IDCourse,
d.name as course_name,
d.slug,
d.short_description,
d.address,
e.city_name,
e.state_code,
d.zip,
e.city_slug,
e.state_slug,
h.IDDestination,
LOWER(e.iso_code) as country_slug, a.*,
b.IDTeetimeType,
c.name as teetime_type,
b.start_time,b.end_time,
(case dayofweek(a.teetime_dt)
when 1 then `b`.`sun`
when 2 then `b`.`mon`
when 3 then `b`.`tue`
when 4 then `b`.`wed`
when 5 then `b`.`thu`
when 6 then `b`.`fri`
when 7 then `b`.`sat`
end) AS `price`, g.tax_rate, f.alias
from cart_course_teetimes a
join course_priceplan b
on a.IDCoursePricePlan = b.IDCoursePricePlan
join course_teetime_type c
on b.IDTeetimeType = c.IDTeetimeType
join course d
on b.IDCourse = d.IDCourse
join vw_cities e
on d.IDCity = e.IDCity
join destinations_cities h
on h.IDCity= d.IDCity
LEFT JOIN (SELECT * FROM media_mapping WHERE is_main_item=1 AND IDGalleryType=3) f
ON d.IDGallery = f.IDGallery
left join course_tax
g on a.IDCourseTax = g.IDCourseTax
where a.IDCart = :cart_id
order by d.name, a.teetime_dt, b.start_time;";
$prepared = array(
"cart_id" => $idCart,
);
$conn = new DBConnection();
$results = $conn->fetch($query, $prepared);
$conn = null;
$results = !empty($results) ? $results : array();
$id = null;
foreach($results as $row) {
// Set ID for the first record.
if($id === null)
$id = $row['IDDestination'];
// will stay true, otherwise it's false and we should kill the loop.
if($id != $row['IDDestination']) {
$newid=$row['IDDestination'];
echo "<script type='text/javascript'> emptycart();</script>";
$query = "DELETE FROM cart_course_teetimes a WHERE h.IDDestination='.$id.'";
$res =mysql_query($query) or die (mysql_error());
break;
}
}
This is incorrect PHP:
$query = "DELETE FROM cart_course_teetimes a WHERE h.IDDestination='.$id.'"
You're already inside a "-quoted string, so . PHP concatenation operators aren't operators, they're just a period.
You want either of these instead:
$query = "DELETE FROM cart_course_teetimes a WHERE h.IDDestination='" . $id . "'";
$query = "DELETE FROM cart_course_teetimes a WHERE h.IDDestination='$id'"
Right now you're producing
... WHERE h.IDDestination = .42.
which is not valid SQL.
Plus it appears you're mixing database libraries. You've got $conn->fetch() which implies you're using one of the OO db libraries (mysqli? pdo? custom wrapper?). But you then call mysql_query(). Unless you've EXPLICITLY called mysql_connect(), that delete query will never execute. Database connections made in one of the libraries are utterly useless in any of the other libraries.

Getting total in while statement with UNION query

I am trying to calculate how much a user has earned so it reflects on the users home page so they know how much their referrals have earned.
This is the code I have.
$get_ref_stats = $db->query("SELECT * FROM `members` WHERE `referral` = '".$user_info['username']."'");
$total_cash = 0;
while($ref_stats = $get_ref_stats->fetch_assoc()){
$get_ref_cash = $db->query("SELECT * FROM `completed` WHERE `user` = '".$ref_stats['username']."' UNION SELECT * FROM `completed_repeat` WHERE `user` = '".$ref_stats['username']."'");
$countr_cash = $get_ref_cash->fetch_assoc();
$total_cash += $countr_cash['cash'];
$countr_c_rate = $setting_info['ref_rate'] * 0.01;
$total_cash = $total_cash * $countr_c_rate;
}
It worked fine when I just had
$get_ref_cash = $db->query("SELECT * FROM `completed` WHERE `user` = '".$ref_stats['username']."'");
but as soon as I added in the UNION it no longer calculated correctly.
For example, there is 1 entry in completed and 1 entry in completed_repeat both of these entries have a cash entry of 0.75. The variable for $countr_c_rate is 0.10 so $total_cash should equal 0.15 but instead it displays as 0.075 with and without the UNION it acts as if it is not counting from the other table as well.
I hope this makes sense as I wasn't sure how to explain the issue, but I am very unsure what I have done wrong here.
In your second query instead of UNION you should use UNION ALL since UNION eliminates duplicates in the resultset. That is why you get 0.075 instead of 0.15.
Now, instead of hitting your database multiple times from client code you better calculate your cash total in one query.
It might be inaccurate without seeing your table structures and sample data but this query might look like this
SELECT SUM(cash) cash_total
FROM
(
SELECT c.cash
FROM completed c JOIN members m
ON c.user = m.username
WHERE m.referral = ?
UNION ALL
SELECT r.cash
FROM completed_repeat r JOIN members m
ON r.user = m.username
WHERE m.referral = ?
) q
Without prepared statements your php code then might look like
$sql = "SELECT SUM(cash) cash_total
FROM
(
SELECT c.cash
FROM completed c JOIN members m
ON c.user = m.username
WHERE m.referral = '$user_info['username']'
UNION ALL
SELECT r.cash
FROM completed_repeat r JOIN members m
ON r.user = m.username
WHERE m.referral = '$user_info['username']'
) q";
$result = $db->query($sql);
if(!$result) {
die($db->error()); // TODO: better error handling
}
if ($row = $result->fetch_assoc()) {
$total_cash = $row['cash_total'] * $setting_info['ref_rate'];
}
On a side note: make use of prepared statements in mysqli instead of building queries with concatenation. It's vulnerable for sql-injections.
With $countr_cash = $get_ref_cash->fetch_assoc(); you only fetch the first row of your result. However, if you use UNION, you get in your case two rows.
Therefore, you need to iterate over all rows in order to get all values.
Ok, So there is only one row in members table. You are iterating only once on the members table. Then you are trying to get rows using UNION clause which will result in two rows and not one. Then you are just getting the cash column of the first row and adding it to the $total_cash variable.
What you need to do is iterate over the results obtained by executing the UNION query and add the $total_cash variable. That would give you the required result.
$get_ref_stats = $db->query("SELECT * FROM `members` WHERE `referral` = '".$user_info['username']."'");
$total_cash = 0;
while($ref_stats = $get_ref_stats->fetch_assoc()){
$get_ref_cash = $db->query("SELECT * FROM `completed` WHERE `user` = '".$ref_stats['username']."' UNION SELECT * FROM `completed_repeat` WHERE `user` = '".$ref_stats['username']."'");
while($countr_cash = $get_ref_cash->fetch_assoc()){
$total_cash += $countr_cash['cash'];
}
$countr_c_rate = $setting_info['ref_rate'] * 0.01;
$total_cash = $total_cash * $countr_c_rate;
}

Does mysql_fetch_array reset the query var?

For example I have a mysql query that gets some data. Then runs another query based some of the data that it got.
If i just return the first query, in my case $qOne. Everything works great.
BUT, after using my while loop while ($row = mysql_fetch_array($qOne)) It then returns as an empty array. (but the second query I return DOES work)
I tried to see if I could "save" the first query in another var im not messing with like this $savedResult = $qOne, then i'd just return the $savedResult but that did not work.
Does anyone know how I can get my function below to return both of the results? Thanks!
function getFoods($sort, $start, $limit) {
$qOne = mysql_query("SELECT a.id, a.name, a.type, AVG(b.r) AS fra, COUNT(b.id) as tvotes FROM `foods` a LEFT JOIN `foods_ratings` b ON a.id = b.id GROUP BY a.id ORDER BY fra DESC, tvotes DESC LIMIT $start, $limit;");
$i = 0;
$qry = "";
while ($row = mysql_fetch_array($qOne)) {
$fid = $row['id'];
if ($i > 0)
$qry .= " UNION ";
$i++;
$qry .= "SELECT fid, ing, amount FROM foods_ing WHERE fid='$fid'";
}
$qTwo = mysql_query($qry);
return array($qOne, $qTwo);
}
When you have returned the two query result resources, remember that you will need to fetch from them when you actually want to use them. (we don't see the code where you implement that).
To make use of $qOne after you already have looped through it, you must rewind it back to the first position. That is done with mysql_data_seek()
mysql_data_seek($qOne, 0);

Categories