Re-writing several individual SQL query's into one [duplicate] - php

This question already has answers here:
MySQL - Counting two things with different conditions
(4 answers)
Closed 2 years ago.
I have a database where I'm displaying numbers of rows from different columns of a table, as statistics for a site. In pure text, it looks like this (english translation):
"At the moment, there are 86 questions registered. 16 are in the category of history, 6 in the category of geography."
My PHP script is pretty simple:
$question_query = mysqli_query($conn, 'SELECT Q_id FROM questions');
$question_result = mysqli_num_rows($question_query);
$historie_query = mysqli_query($conn, "SELECT Q_id FROM questions WHERE category LIKE '%Historie%'");
$historie_result = mysqli_num_rows($historie_query);
$geografi_query = mysqli_query($conn, "SELECT Q_id FROM questions WHERE category LIKE '%Geografi%'");
$geografi_result = mysqli_num_rows($geografi_query);
echo '<h3>' . 'For øyeblikket er det ' . '<b>' . $question_result . '</b>' . ' spørsmål i databasen:' . '</h3>';
echo '<ul>' . '<li>' . '<b>' . $historie_result . '</b>' . ' historie-spørsmål.' . '</li>' ;
echo '<li>' . '<b>' . $geografi_result . '</b>' . ' geografi-spørsmål.' . '</li>' . '</ul>';
This works well, but right now it's only doing 3 queries. In the future, it will probably be about 10 or 15 queries.
I've tried to join these into one, but it's only outputting the first query:
$query = "SELECT Q_id FROM questions";
"SELECT Q_id FROM questions WHERE category LIKE '%Historie%'";
"SELECT Q_id FROM questions WHERE category LIKE '%Geografi%'";
$result = mysqli_query ($conn, $query);
$count = mysqli_num_rows($result);
print_r ($count);
I figured a while loop might be able to solve that, but when I replace the print_r with the while loop, I get an undefined variable error for the different row counts ($question_count, $historie_count, $geografi_count):
while ($row = mysqli_fetch_assoc($result)) {
$row[0] = $question_count;
$row[1] = $historie_count;
$row[2] = $geografi_count;
print_r ($question_count . '</br>' . $historie_count . '</br>' . $geografi_count);
}
How could I go about making this into one query? And, is that desirable, or is it better to keep the queries separated?
Thanks in advance!

Use conditional aggregation:
select
count(*) question_count,
sum(category like '%Historie%') historie_count,
sum(category like '%Geografi%') geografi_count
from questions

Related

Searching multiple tables and columns with a keyword in php [duplicate]

This question already has answers here:
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 3 years ago.
I am building an android application which uses mysql database as backend. I am trying to search through tables and multiple columns with a keyword and return them to the android app using php in a json format.
I tried a sample code i got from this question but it doesn't seem to work.
Here is my php code
<?php
require "conn.php";
$key = $_POST["key"];
$array = array();
$mysql_query = "(SELECT *, 'home' AS type FROM home WHERE food_name LIKE '%" . $key . "%' OR descrip LIKE '%" . $key ."%' OR user_name LIKE '%" . $key ."%'
UNION
SELECT *, 'c4c' AS type FROM cook4cash WHERE food_name LIKE '%" . $key . "%' OR descrip LIKE '%" . $key ."%' OR user_name LIKE '%" . $key ."%'
UNION
SELECT *, 'vendor' AS type FROM vendors_info WHERE user_name LIKE '%" . $key . "%'
UNION
SELECT *, 'customer' AS type FROM customers_info WHERE user_name LIKE '%" . $key . "%')";
mysql_query($query);
$result = mysqli_query($conn, $mysql_query);
if(mysqli_num_rows($result) > 0){
session_start();
while($row = mysqli_fetch_assoc($result)){
$array[] = $row;
//echo json_encode($row);
}
foreach($array as $new_array){
$new_array['id'] . '<br/>';
$new_array['food_name'] . '<br/>';
$new_array['descrip'] . '<br/>';
$new_array['price'] . '<br/>';
$new_array['quantity'] . '<br/>';
$new_array['image_url'] . '<br/>';
$new_array['user_name'] . '<br/>';
$new_array['profile_pic'] . '<br/>';
$new_array['delivery_time'] . '<br/>';
$new_array['delivery_cost'] . '<br/>';
$new_array['location'] . '<br/>';
$new_array['email'] . '<br/>';
}
echo json_encode(array("userInfo" => $array));
} else {
echo "No data was found";
}
?>
When i use postman to test, it gives the error code 500 (Internal Server Error).
I want to know what is wrong with this code.
Did you check PHP error_logs? I guess reason of the problem is line 14. You're using mysqli_* methods but on line 14, you had tried to use a mysql_* method. I think you should remove the code on this line and try again.

Show the total amount of a column

I'm currently making a game to teach myself PHP as I go. I've already progressed quite a bit but I'm stuck now at the statistics where I want to show how many of each player-class there currently is in the game.
Thanks everyone, finally managed to fix it - not in the way as answered but the answer did help me getting to a result!
Which is:
<?php
echo '<b>Current Classes in the Game :</b>' . '<br />';
$result = $db->query("SELECT COUNT(*) FROM users WHERE role='Warrior'");
$row = $result->fetch_row();
echo $row[0] . ' Warriors' . '<br />';
$result = $db->query("SELECT COUNT(*) FROM users WHERE role='Mage'");
$row = $result->fetch_row();
echo $row[0] . ' Mages' . '<br />';
$result = $db->query("SELECT COUNT(*) FROM users WHERE role='Priest'");
$row = $result->fetch_row();
echo $row[0] . ' Priests' . '<br />';
$result = $db->query("SELECT COUNT(*) FROM users WHERE role='Rogue'");
$row = $result->fetch_row();
echo $row[0] . ' Rogues' . '<br />';
?>
You need execute an sql query like this using mysqli :
select
count(*) as nb,
class
from
yourTable
group by class

How to display the whole table of my job including their categories that I had to create from mySQL Workbench to php?

This is my php code for displaying the table from mySQL workbench:
$stmt = $pdo->prepare(' SELECT jobs.*, categories.category_name
FROM jobs
LEFT JOIN vacancies.categories ON categories.category_id = jobs.category_id
WHERE jobs.category_id =:category_id');
$choice = 0;// just a temp for test
$criteria = [
'category_id' => $choice,
];
$stmt -> execute($criteria);
while ($row = $stmt->fetch()){
echo '<br>' . $row['id']. ' ' . $row['title']. ' ' . $row['salary']. ' ' . $row['location']. ' ' . $row['description']. '<br> category is:'.$row['category_name'].'</br>';
}
Now if I run this and check my webpage it only shows the jobs that hve the category_id of the $choice I put but I want to display all of the job table.
I have a category table with 6 categories (0 is the start) and in my other table that is called jobs. I have 7 jobs with their details.
I hope someone understand what I am trying to say and can help me out. Ask me anything if I don't give out enough.
You are using a prepared query to norrow the results to a defined criteria. If you want to display all the jobs you should simply remove the WHERE tag and use a simple query
$stmt = $pdo->query(' SELECT jobs.*, categories.category_name
FROM jobs
LEFT JOIN vacancies.categories ON categories.category_id = jobs.category_id');
echo '<table>';
while ($row = $stmt->fetch()){
echo '<tr><td>' . $row['id']. '</td><td>' . $row['title']. '</td><td>' . $row['salary']. '</td><td>' . $row['location']. '</td><td>' . $row['description'].'</td><td> category is:'.$row['category_name'].'</td></tr>';
}
echo '</table>';

MySQL does not retrieve first item in PHP

I've now been trying for hour and can't figure the problem out. I've made a php file that fetch all items in a table and retrieves that as JSON. But for some reason after I inserted the second mysql-query, it stopped fetching the first item. My code is following:
...
case "LoadEntryList":
$result2 = performquery("SELECT * FROM Entries WHERE Category = '" . $_POST["Category"] .
"' LIMIT " . $_POST["Offset"] . ", " . $_POST["Quantity"] . "");
$row2 = $result2->fetch_assoc();
while($row = $result2->fetch_assoc()) {
$result3 = performquery("SELECT Username FROM Users WHERE ID = '" . $row2["UserID"] . "'");
$row3 = $result3->fetch_assoc();
echo substr(json_encode($row),0,
strlen(json_encode($row))-1) . ",\"Username\":\"" . $row3["Username"] . "\"}";
}
...
Any help is greatly appreciated.
EDIT: Thanks for all those super fast responses.
First you're fetching a row:
$row2 = $result2->fetch_assoc();
Then you start looping at the next row:
while($row = $result2->fetch_assoc()) {
If you want to loop over all of the rows, don't skip the first one. Just loop over all of the rows:
$result2 = // your very SQL-injectable query
while($row2 = $result2->fetch_assoc()) {
$result3 = // your other very SQL-injectable query
$row3 = $result3->fetch_assoc();
// etc.
}
Note that errors like this would be a lot more obvious if you used meaningful variable names. "row2", "result3", etc. are pretty confusing when you have overlapping levels of abstraction.
Important: Your code is wide open to SQL injection attacks. You're basically allowing users to execute any code they want on your database. Please look into using prepared statements and treating user input as values rather than as executable code. This is a good place to start reading, as is this.
No Need of $row2 = $result2->fetch_assoc();
<?
case "LoadEntryList":
$result2 = performquery("SELECT * FROM Entries WHERE Category = '" . $_POST["Category"] .
"' LIMIT " . $_POST["Offset"] . ", " . $_POST["Quantity"] . "");
while($row = $result2->fetch_assoc())
{
$result3 = performquery("SELECT Username FROM Users WHERE ID = '" . $row["UserID"] . "'");
$row3 = $result3->fetch_assoc();
echo substr(json_encode($row),0,strlen(json_encode($row))-1) . ",\"Username\":\"" . $row3["Username"] . "\"}";
}
?>
Or,
<?
...
case "LoadEntryList":
$Category=$_POST["Category"];
$Offset=$_POST["Offset"];
$Quantity=$_POST["Quantity"];
$result3 = performquery("SELECT Entries.*, Users.Username FROM Entries, Users WHERE Entries.Category=$Category AND Entries.UserID=Users.ID LIMIT $Offset, $Quantity");
$row3 = $result3->fetch_assoc();
echo substr(json_encode($row),0,strlen(json_encode($row))-1) . ",\"Username\":\"" . $row3["Username"] . "\"}";
}
...
?>
I have a addition to David answer(can't comment on it yet)
This line of code:
$result3 = performquery("SELECT Username FROM Users WHERE ID = '" . $row2["UserID"] . "'");
will always return with the same result. If you were to change $row2[... into $row[... the code would take the rows that get updated by the while loop.
I am not content with the accepted result. The snippet can be fixed / replaced, and also a bad code must be replaced. Also not to mention is that I don't know if anyone spotted a really big mistake in the output. Here is the fix and I'll explain why.
$JSON = array();
$result2 = performquery( '
SELECT
e.*, u.Username
FROM Entries AS e
LEFT JOIN Users AS u ON u.ID = e.UserID
WHERE
e.Category = ' . $_POST['Category'] . '
LIMIT ' . $_POST['Offset'] . ', ' . $_POST['Quantity'] . '
' );
while( $row2 = $result2->fetch_assoc() ){
$JSON[] = $row2;
}
echo json_encode( $JSON );
Obviously the main issue is the query, so I fixed it with a LEFT JOIN, now the second part is the output. First it's the way you include the username, and the second what if you had multiple results? Than your output will be:
{"ID":1,"Username":"John"}{"ID":2,"Username":"Doe"}
How do you parse it? So the $JSON part comes in place. You add it to an array and will encode that array. Now the result is:
{["ID":1,"Username":"John"],["ID":2,"Username":"Doe"]}
LE: I left out the sql inject part which as stated by the OP, will be done afterwards? I'm not sure why not do it at the point of writing it, because you may forget later on that you need to sanitize it.

Displaying Expenses under each expense type using MySQL PDO

I have two tables that I am creating a list that shows all the expenses under each expense type. I have been able to get it to work except when I add the
AND WHERE expenses.pid = " . $pid
it cases a Syntax error and I can't figure out way.
The biggest thing is I need to limet the Expense Type to only show the ones that have some data to go below them
EXPENSETYPE
typeid
pid
exptype
EXPENSES
expid
pid
expdate
checktype
payee
typeid
details
amount
<?php
$pid = 6;
$sql = "SELECT expensetype.typeid, expensetype.exptype
FROM `expensetype` WHERE expensetype.pid = $pid
ORDER BY expensetype.typeid DESC";
$expensetype = $db->query($sql);
foreach($expensetype as $type) {
echo '<li>' . $type['exptype'] . '<ul>';
$sql2 = "SELECT expenses.expid, expenses.expdate, expenses.checktype, expenses.payee, expenses.details, expenses.amount
FROM `expenses` WHERE `expenses`.typeid = " . $type['typeid'] . "AND WHERE expenses.pid = " . $pid ;
$expenses = $db->query($sql2);
foreach($expenses as $exp) {
echo '<li>' . $exp['expdate'] . ' ' . $exp['checktype'] . ' ' . $exp['expdate'] . ' ' . $exp['payee'] . ' ' . $exp['details'] .' ' . $exp['amount'] .'</li>';
}
echo '</ul></li>';
}
?>
Try this SQL statement instead of making two of them :
SELECT `expensetype`.`typeid`, `expensetype.exptype`, `expenses`.`expid`,
`expenses`.`expdate`, `expenses`.`checktype`, `expenses`.`payee`,
`expenses`.`details`, `expenses`.`amount`
FROM `expensetype` INNER JOIN `expenses` ON
`expensetype`.`typeid` = `expense`.`typeid`
WHERE (...)
Also, you cannot use two WHERE in a SQL statement, only use AND.

Categories