PHP MYSQL - Combine Query From Another Variable - php

May I know if I can combine queries from different variable or is there any other way. I want to insert $query_1 to $query_2
Example:
$sql = "SELECT l_id from mlk";
$result = mysqli_query($conn, $sql);
$count = mysqli_num_rows($result);
if (mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_assoc($result)) {
$l_id[] = $row["l_id"];
}
}
mysqli_free_result($result);
foreach($l_id as $row){
$query_1= "(select count(*) from staff s where s.l_id = $row) as mlk_$row,";
}
$query_2= "SELECT mlk.lokasi,
//insert $query_1 here
from mlk INNER JOIN staff WHERE staff.l_id=mlk.l_id GROUP BY mlk.lokasi";
$result = mysqli_query($conn, $sql);
mlk is a table that stores staff working location
$query_2 will display the Location Name and I also want to display the total number of staff on that particular location. eg, Kuala Lumpur, 10

Just include the counting in the 2nd query:
SELECT mlk.lokasi, count(*) as no_of_staff
from mlk
INNER JOIN staff on staff.l_id=mlk.l_id
GROUP BY mlk.lokasi
I also changed the implicit join into an explicit one by moving the join condition from the where clause to the on clause.

Use left join for this to show all the locations and then each location staff count.
SELECT mlk.lokasi, count(*) as no_of_staff
from mlk
LEFT JOIN staff on staff.l_id=mlk.l_id
GROUP BY mlk.lokasi order by mlk.lokasi ASC

Related

Showing two different values depending on SESSION value in INNER JOIN

I have two different tables, one named users, and another named transactions. Transactions contains wallet1, wallet2, amount. Users contains user details such as firstname, lastname, and wallet. I am trying to display the corresponding first name and last name, depending on whether or not the SESSION_wallet is equal to wallet1 or wallet2 within transactions. I tried searching for a while, and came up with a solution for showing the correct display name for the first and last name making the transfer, however, I am trying to make it display the correct value for "Transfer to:"
Here is some of my code to get a better understanding of what I mean:
MySQLi Query:
$result2 = mysqli_query($link, "SELECT * FROM transactions INNER JOIN users ON transactions.wallet1 = users.wallet WHERE transactions.wallet1 = '" . $_SESSION["wallet"] . "' OR transactions.wallet2 = '" . $_SESSION["wallet"] . "' Order by transactions.id DESC LIMIT 5 ");
PHP Code:
<?php
if(mysqli_num_rows($result2) > 0)
{
while($row = mysqli_fetch_array($result2))
{
?>
The table that needs to display the transfer from, and transfer to:
<?php
if ($_SESSION["wallet"] == $row["wallet1"]) {
echo "<td>Transfer to ".$row["firstname"]." ".$row["lastname"]."</td>";
}
else if ($_SESSION["wallet"] == $row["wallet2"]) {
echo "<td>Transfer from ".$row["firstname"]." ".$row["lastname"]."</td>";
}
?>
Right now my tables are only showing the first and last name of the user that made the Transfer, however, I need it to display the first and last name of the user that the transaction is made to as well. The else if code is working correct, but the first part is not showing the corresponding value.
You will need to JOIN your transactions table to your users table twice, once to get each users name. Then to avoid duplicate column names overwriting the results in the output array, you will need to use column aliases. Something like this should work:
$result2 = mysqli_query($link, "SELECT t.*,
u1.firstname AS w1_firstname,
u1.lastname AS w1_lastname,
u2.firstname AS w2_firstname,
u2.lastname AS w2_lastname
FROM transactions t
INNER JOIN users u1 ON t.wallet1 = u1.wallet
INNER JOIN users u2 ON t.wallet2 = u2.wallet
WHERE t.wallet1 = '{$_SESSION["wallet"]}'
OR t.wallet2 = '{$_SESSION["wallet"]}'
ORDER BY t.id DESC
LIMIT 5 ");
Then you can access each user's names as $row['w1_firstname'] etc.:
if ($_SESSION["wallet"] == $row["wallet1"]) {
echo "<td>Transfer to ".$row["w2_firstname"]." ".$row["w2_lastname"]."</td>";
}
else if ($_SESSION["wallet"] == $row["wallet2"]) {
echo "<td>Transfer from ".$row["w1_firstname"]." ".$row["w1_lastname"]."</td>";
}
Note that ideally you should use a prepared query for this, for example:
$stmt = $link->prepare("SELECT t.*,
u1.firstname AS w1_firstname,
u1.lastname AS w1_lastname,
u2.firstname AS w2_firstname,
u2.lastname AS w2_lastname
FROM transactions t
INNER JOIN users u1 ON t.wallet1 = u1.wallet
INNER JOIN users u2 ON t.wallet2 = u2.wallet
WHERE t.wallet1 = ?
OR t.wallet2 = ?
ORDER BY t.id DESC
LIMIT 5");
$stmt->bind_param('ss', $_SESSION["wallet"], $_SESSION["wallet"]);
$stmt->execute();
$result2 = $stmt->get_result();

PHP Retrieve information from five different tables with correct order

I develop a chat system where students and staff can exchange different messages. I have developed a database where we have five tables: the staff table, the student, the message and two mapping tables the staff_message and stu_message. These tables contain only the student/staff id and the message id.
My problem is that I cannot order the messages. I mean that I cannot figure out how can I make one SQL statement that will return all messages and be ordered by for example the ID. The code that I have made is this:
$qu = mysqli_query($con,"SELECT * FROM stu_message");
while($row7 = mysqli_fetch_assoc($qu)){
$que = mysqli_query($con, "SELECT * FROM student WHERE studentid =".$row7['stu_id']);
while($row8 = mysqli_fetch_assoc($que)) {
$username = $row8['username'];
}
$query3 = mysqli_query($con, "SELECT * FROM message WHERE id=".$row7['mid']);
while($row6 = mysqli_fetch_assoc($query3)) {
echo $row6['date']."<strong> ".$username."</strong> ".$row6['text']."<br>";
}
}
$query2 = mysqli_query($con, "SELECT * FROM staff_message");
while($row3 = mysqli_fetch_assoc($query2)){
$query = mysqli_query($con, "SELECT * FROM staff WHERE id =".$row3['staff_id']);
while($row5 = mysqli_fetch_assoc($query)) {
$username = $row5['username'];
}
$query3 = mysqli_query($con, "SELECT * FROM message WHERE id=".$row3['m_id']);
while($row6 = mysqli_fetch_assoc($query3)) {
echo $row6['date']."<strong> ".$username."</strong> ".$row6['text']."<br>";
}
}
?>
The result is different from that I want. To be more specific first are shown the messages from the students and then from the staff. My question is, is there any query that it can combine basically all these four tables in one and all messages will be shown in correct order? for example by the id?
Thank you in advance!
First, use JOIN to get the username corresponding to the stu_id or staff_id, and the text of the message, rather than separate queries.
Then use UNION to combine both queries into a single query, which you can then order with ORDER BY.
SELECT u.id, u.text, u.username
FROM (
SELECT s.username, m.text, m.id
FROM message AS m
JOIN stu_message AS sm ON m.id = sm.mid
JOIN student AS s ON s.id = sm.stu_id
UNION ALL
SELECT s.username, m.text, m.id
FROM message AS m
JOIN staff_message AS sm ON m.id = sm.m_id
JOIN staff AS s ON s.id = sm.staff_id
) AS u
ORDER BY u.id

how to limit retrieve to only 1 random work for one user instead of all the works

I have 2 tables userdatafiles & users, where i merge the 2 tables together based on common ID, to find the corresponding works attached to the ID, the following PHP code i have retrieve the works from the user, it works fine as i only want to show 1 work per user, but if a user have 2-3 works for example, it will also display the different works out..
PHP
<?php
include 'dbAuthen.php';
$sql = 'SELECT * FROM userdatafiles JOIN users ON userdatafiles.UserID = users.UserID WHERE Specialisation = "Painting"';
$result = mysqli_query($con,$sql);
if (mysqli_num_rows($result) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($result)) {
$links[] = array(
"links" => $row["Link"],
"caption" => $row["Name"],
);
}
shuffle($links);
echo json_encode($links);
} else {
echo "0 results";
}
?>
the above code works if i only uploaded 1 work per user, what should i do to improve the code so that if a user have multiple works, it will only display a random work among the many that user has? Thanks..
use rand() for random display and set limit to 1 so you will get one random record
ORDER BY RAND() LIMIT 1
so your query will be:
$sql = 'SELECT * FROM userdatafiles JOIN users ON userdatafiles.UserID = users.UserID WHERE Specialisation = "Painting" ORDER BY RAND() LIMIT 1';
Use DISTINCT to eliminate repeating userid:
$sql = 'SELECT DISTINCT(users.UserID),name,link FROM userdatafiles JOIN users ON userdatafiles.UserID = users.UserID WHERE Specialisation = "Painting" ORDER BY RAND()';
or use GROUP BY:
$sql = 'SELECT users.UserID,name,link FROM userdatafiles JOIN users ON userdatafiles.UserID = users.UserID WHERE Specialisation = "Painting" GROUP BY UserID ORDER BY RAND()';

total sum of a row

I have this query which gives me the transactions for a user, and the output is a table with the information. There is this row named basket_value which contains some numbers, and I need to get the sum of those numbers. Could you please help me?
$query3 = 'SELECT users.first_name,users.last_name,users.phone,
retailer.date, SUM(retailer.basket_value),
retailer.time,retailer.location,retailer.type_of_payment
FROM users ,retailer
WHERE users.user_id="'.$id_user.'"
AND users.user_id=retailer.user_id GROUP BY users.user_id';
$result3 = mysql_query($query) or die(mysql_error());
// Print out result
while($row = mysql_fetch_array($result3)) {
echo "Total ". $row['user_id']. " = $". $row['SUM(basket_value)'];
echo "<br />";
}
I suppose that also your query have some problem and suppose that you have an id to retrieve users, I would do in that way
$query3 = 'SELECT users.user_id,users.first_name,users.last_name,
users.phone, retailer.date,
SUM(retailer.basket_value) as total_sum,
retailer.time,retailer.location,retailer.type_of_payment
FROM users ,retailer WHERE users.user_id="'.$id_user.'"
AND users.user_id=retailer.user_id
GROUP BY users.user_id,users.first_name,users.last_name,
users.phone, retailer.date,retailer.time,retailer.location,
retailer.type_of_payment '
$result = $mysqli->query($query3);
Now if you want the sum for each user:
while ($row = $result->fetch_row()) {
echo "Player: ".$row['user_id']." total: ".$row['total_sum'];
}
If you want the WHOLE GLOBAL sum, you have to way:
Modify your query in that way:
SELECT SUM(retailer.basket_value) as total_sum
FROM retailer
Sum into while loop like: $total += $row['total_sum'];
You're missing a GROUP BY on your query. You most likely want to add GROUP BY users.user_id
Try this query:
SELECT u.first_name, u.last_name, u.phone, SUM(r.basket_value) as total_sum
FROM users u
JOIN retailers r
ON u.user_id = r.user_id
WHERE u.user_id="'.$id_user.'"
GROUP BY u.user_id
You can omit all other columns in the select list and only have the sum() aggregate run on the set to avoid the GROUP BY clause.
$query3 = 'SELECT SUM(retailer.basket_value) as total_sum
FROM users ,retailer WHERE users.user_id="'.$id_user.'"
AND users.user_id=retailer.user_id';

How to send SQL count data & array data together?

I have a script designed to print out values of students who have accrued more than 3 tardies. I want this script to print out both the student name, and the amount of times they've been tardy, but so far I've been only able to print out their names with the following script:
$sql = "select DISTINCT StudentID,classid,date from attendance_main where status = 'Tardy' AND classid like '%ADV%'";
$result = mysql_query($sql) or die (mysql_error());
while($row=mysql_fetch_array($result)) {
$studentid = $row['StudentID'];
$sql2 = "select distinct StudentID,classid,date from attendance_main where StudentID = '$studentid' AND status = 'Tardy' AND classid like '%ADV%'";
$result2 = mysql_query($sql2) or die (mysql_error());
while($row2=mysql_fetch_array($result2)) {
$tardycount = mysql_num_rows($result2);
$studentid = $row2['StudentID'];
if($tardycount >= 3) {
$sql3 = "select * from students where rfid = '$studentid'";
$result3 = mysql_query($sql3) or die (mysql_error());
while($row3=mysql_fetch_array($result3)) {
$fname[] = $row3['fname'];
}
}
}
}
$newdata = array_unique($fname);
foreach ($newdata as $value) {
echo $value;
}
I can't think of how to intuitively do this. Keeping it all in the while loop didn't work (I had multiple results coming up for the same students despite requesting unique entries) so using array_unique was the only method I could think of.
Thanks for any help!
Something like this:
SELECT
attendance_main.StudentID,
students.fname,
COUNT(attendance_main.*) AS `times_tardy`
FROM
attendance_main
INNER JOIN
students
ON
attendance_main.StudentID = students.rfid
WHERE
attendance_main.status = 'Tardy'
AND
attendance_main.classid like '%ADV%'
GROUP BY
attendance_main.StudentID
HAVING
`times_tardy` > 3
Joining the two tables gets you the tardy count and student's name in one query, and the GROUP BY and HAVING clause that get you only the students with more than 3 tardy entries.
You can (and should) do almost everything in SQL. It should look something like this.
select StudentID, classid, date count(*)
from attendance_main
where status = 'Tardy' AND classid like '%ADV%'"
left join student on student.rfid = attendance_main.StudentId
group by StudentId
having count(*) > 3;
Here's how it works.
select the results you want to work with:
select StudentID, classid, date count(*)
from attendance_main
where status = 'Tardy' AND classid like '%ADV%'"
Join the students to your result set on the common id
left join student on student.rfid = attendance_main.StudentId
group everything by student. We use count(*) to get the number of items. We know we're only dealing with tardies because of the where clause in the select.
group by StudentId
limit the results to only tardies above 3 with the having claues (this is like a where clause for the group by)
having count(*) > 3;

Categories