Join columns from two mysql tables - php

I'm trying to figure out the following. In the beginning I want to check if a member is in groups 11, 43 or 1.
I have the following tables with columns:
table members (member_id, name, group)
334 Ronald 43
table content (member_id, value)
334 Gold
I'm looking for a query which displays the name FROM members and value FROM content, joined with member_id and end result something like
Ronald Gold
If the user is not in the groups I have set, he/she will not be displayed.
The following is what i have managed to do
$sql = 'SELECT * FROM members m INNER JOIN content p ON m.member_id = p.member_id ';
$retval = mysql_query( $sql, $conn );
and
while($row = mysql_fetch_array($retval, MYSQL_ASSOC)) {
echo $row['member_id']. " " .$row['value'];
echo "<br>";
}
will output 334 Gold.
I just need to check the group in the beginning and replace member_id with name in the final output. Any help?

Just adjust your mysql query:
$sql = 'SELECT m.name, p.value FROM members m JOIN content p ON m.member_id = p.member_id WHERE m.group = 1 OR m.group = 11 OR m.group = 43;
then
echo $row['name']. " " .$row['value'];
Also you should be using mysqli_query() or PDO::query() since mysql_query() is deprecated. Reference

When you're echoing the results if you change echo $row['member_id'] to echo $row['name'] you will get the member's name.
Returning $row['group'] will tell you which group the member is in.

Your SQL should return following construct for each row
(member_id, name, group, value)
to filter out members not in desired groups modify your query
$sql = 'SELECT * FROM members m INNER JOIN content p ON m.member_id = p.member_id WHERE m.group IN (11,43,1) ';
Side note:
Consider using PDO or mysqli_* instead of mysql_* as mysql_* is deprecated and gone in PHP7

Related

Only the last record from the database is displayed

I connected, I created a quick script in which I want to manage clients, domains and notes.
The problem is that when I add 2 notes to the client from ID: 1 - after viewing I see only one.
The following code shows what I have done so far
SQL Query:
$sql = "SELECT * FROM domain JOIN note ON domain.id = note.domain_id GROUP BY domain.id";
My PHP code:
while($rs = $resultdb->fetch_array(MYSQLI_ASSOC)) {
echo '<tr>';
echo '<td>'.$rs["id"].'</td>';
echo '<td><strong>'.$rs["domain_name"].'</strong></td>';
echo '<td>'.$rs["note"].'</td>';
echo '</tr>';
}
The result he gets is:
ID DOMAIN NOTE
1 "domain1.com" "note 1 to domain1.com"
2 "domain2.com" "note 2 to domain2.com"
However, in the database I have added a few notes to domain1.com.
I would like to see all the notes added to a given domain.
EDIT:
When I do: "SELECT * FROM domain JOIN note ON domain.id = note.domain_id";
I getting:
I getting
I expect
EDIT: Add screnshot
LEFT JOIN
Your GROUP BY is limiting the records retrieved by the query. If you want all of the notes together you can try using GROUP_CONCAT() to produce a single field with all of the notes in one...
$sql = "SELECT domain.id as id, domain.domain_name as domain_name,
GROUP_CONCAT(note.note) as note
FROM domain
LEFT JOIN note ON domain.id = note.domain_id
GROUP BY domain.id";
You might also change the JOIN to LEFT JOIN in case there are no notes for a particular domain.
Probably you need to use a separate query to get "Domain Notes" in the while. for example:
while ($rs = $resultdb->fetch_array(MYSQLI_ASSOC)) {
$sql_notes = "SELECT * FROM notes WHERE domain_id = '" . (int)$rs['domain_id'] . "'";
...
}
you need group_concat group by note.domain_id
if you need exact match the use inner join
"SELECT id, domain, group_concat(note) as note
FROM domain
INNER JOIN note ON domain.id = note.domain_id
GROUP BY note.domain_id";
if you needc result also for id without notes then try
"SELECT id, domain, (group_concat(ifnull(note,'')) as note
FROM domain
LEFT JOIN note ON domain.id = note.domain_id
GROUP BY note.domain_id";

Echo contents of JOIN SQL tables with MySQLi

I'm working on a system, and this module is supposed to echo the contents of the database.
It worked perfectly until I added some JOIN statements to it.
I've checked and tested the SQL code, and it works perfectly. What's not working is that part where I echo the content of the JOINed table.
My code looks like this:
$query = "SELECT reg_students.*, courses.*
FROM reg_students
JOIN courses ON reg_students.course_id = courses.course_id
WHERE reg_students.user_id = '".$user_id."'";
$result = mysqli_query($conn, $query);
if (mysqli_fetch_array($result) > 0) {
while ($row = mysqli_fetch_array($result)) {
echo $row["course_name"];
echo $row["course_id"];
The course_name and course_id neither echo nor give any error messages.
UPDATE: I actually need to increase the query complexity by JOINing more tables and changing the selected columns. I need to JOIN these tables:
tutors which has columns: tutor_id, t_fname, t_othernames, email, phone number
faculty which has columns: faculty_id, faculty_name, faculty_code
courses which has columns: course_id, course_code, course_name, tutor_id, faculty_id
I want to JOIN these tables to the reg_students table in my original query so that I can filter by $user_id and I want to display: course_name, t_fname, t_othernames, email, faculty_name
I can't imagine that the user_info table is of any benefit to JOIN in, so I'm removing it as a reasonable guess. I am also assuming that your desired columns are all coming from the courses table, so I am nominating the table name with the column names in the SELECT.
For reader clarity, I like to use INNER JOIN instead of JOIN. (they are the same beast)
Casting $user_id as an integer is just a best practices that I am throwing in, just in case that variable is being fed by user-supplied/untrusted input.
You count the number of rows in the result set with mysqli_num_rows().
If you only want to access the result set data using the associative keys, generate a result set with mysqli_fetch_assoc().
When writing a query with JOINs it is often helpful to declare aliases for each table. This largely reduces code bloat and reader-strain.
Untested Code:
$query = "SELECT c.course_name, t.t_fname, t.t_othernames, t.email, f.faculty_name
FROM reg_students r
INNER JOIN courses c ON r.course_id = c.course_id
INNER JOIN faculty f ON c.faculty_id = f.faculty_id
INNER JOIN tutors t ON c.tutor_id = t.tutor_id
WHERE r.user_id = " . (int)$user_id;
if (!$result = mysqli_query($conn, $query)) {
echo "Syntax Error";
} elseif (!mysqli_num_rows($result)) {
echo "No Qualifying Rows";
} else {
while ($row = mysqli_fetch_assoc($result)) {
echo "{$row["course_name"]}<br>";
echo "{$row["t_fname"]}<br>";
echo "{$row["t_othernames"]}<br>";
echo "{$row["email"]}<br>";
echo "{$row["faculty_name"]}<br><br>";
}
}

PHP Mysql Correctly Iterate Over Tables With Alias Names

I have the following Mysql query:
$sql = "select r.brand AS brand, r.name AS name, r.cost AS cost, e.price AS price, d.shipping as shipping
FROM tab.rawproduct r
INNER JOIN price e ON r.housecode=e.housecode
INNER JOIN product d ON e.productid=d.productid
WHERE r.housecode='$housecode'";
The houscode is assigned to a variable which is then passed to the sql statement:
<label>Housecode:</label><input class="boxes" type="text" name="housecode" value="<?php echo $housecode; ?>"><br />
$housecode = $_POST['housecode'];
Housecode is submitted through a form with action set to $_SERVER[PHP_SELF]
I am trying to iterate over the results with PHP with the following:
$result = $con->query($sql);
if ($result->num_rows >0) {
while($row = mysqli_fetch_array($result)) {
$brand = $row['brand'];
$housecode = $row['housecode'];
$name = $row['name'];
$cost = $row['cost'];
$salesprice = $row['price'];
$shipraw = $row['shipping'];
}
} else {
echo "0 Results";
}
$con->close();
Nothing is getting returned when a user submits a housecode and the "0 Results" is echoed.
I have looked into this problem and read Lucas Knuth's post:
If two or more columns of the result have the same field names, the
last column will take precedence. To access the other column(s) of the
same name, you must use the numeric index of the column or make an
alias for the column. For aliased columns, you cannot access the
contents with the original column name. So, you can either use an AS
in your SQL-query to set other names for the doubled rows or use the
numbered indexes to access them.
So I have used the AS keyword in the above query but I still don't get any results. I have also tried changing to mysqli_fetch_row($result) and tried to assign the $row[0], 1 ... etc instead. Again no luck.
When I run Apache error_log I get the following:
Trying to get property of non-object on line 34. On line 34 and 35 I have:
if ($result->num_rows >0) {
while($row = mysqli_fetch_array($result)) {
Any help would be much appreciated.
Cheers
I have figured out the answer for myself.
The problem was that I was selecting just one database, ie tab.rawproduct BUT tables price e and procduct d are from a totally different database.
So the sql query should have been this:
$sql = "SELECT r.brand, r.name, r.cost, e.price, d.shipping FROM
tab.rawproduct r
INNER JOIN t1.price e on r.housecode=e.housecode
INNER JOIN t1.product d on e.productid=d.productid
WHERE r.housecode = '$housecode' ";
If found the error by checking the mysqli->errno:
if(!$result = $mysqli->query($sql)) {
echo "Error: Our query failed to execute and here is why: \n";
echo "Query: " . $sql . "\n";
echo "Errno: " . $mysqli->errno . "\n";
echo "Error: " . $mysqli->error . "\n";
exit;
}
Hopefully this may help someone else facing the same problem.
Thanks for all your comments and help.
I reproduced your example and I found a bug in your select query: you're missing the r.housecode.
$sql = "select r.brand AS brand, r.name AS name, r.cost AS cost, e.price AS price, d.shipping as shipping, r.housecode AS housecode
FROM tab.rawproduct r
INNER JOIN price e ON r.housecode=e.housecode
INNER JOIN product d ON e.productid=d.productid
WHERE r.housecode='$housecode'";
Check if the cross references match in your tables, because in my examples the rows are correctly returned
table price:
housecode productid price
HT0008 4 3400
HT0008 5 5400
table product:
shipping productid
64 4
78 5
table rawproduct:
brand name cost housecode
Cani bellaaa 63824 HT0008

Multiple mysql table joins with php?

Honestly I have no idea how to do what I am trying to do. I am not overly experienced in php nor in Mysql but I am trying and could use some help, preferably with working example code.
Problem: I have 3 tables
members
customfields
customvals
members contains:
membername | Id
customfields contains:
rank | name
customvals contains
fieldid | userid | fieldvalue
Table columns match at
customvals.userid=members.id
customvals.fieldid=members.rank
What I need to do is match the data so that when page.php?user=membername is called it displays on the page
Table1.membername:<br>
Table2.name[0] - Table3.fieldvalue[0]<br>
Table2.name[1] - Table3.fieldvalue[1]<br>
etc...
(obviously displaying only the information for the said membername)
The more working the code, the more helpful it is for me. Please don't just post the inner join statements. Also it is most helpful to me if you could explain how and why your solution works
So far here is what I have for code:
$profileinfocall = "SELECT Table1.`membername`, Table2.`name`, Table3.`fieldvalue`
FROM members AS Table1
LEFT JOIN customvals AS Table3 ON Table1.`id` = Table3.`userid`
LEFT JOIN customfields AS Table2 ON Table3.`fieldid` = Table2.`rank`
WHERE Table1.`membername` = $username;";
$membercall = "SELECT * FROM members WHERE membername=$username";
$profileinfo = mysql_query($profileinfocall, $membercall);
while($row = mysql_fetch_array($profileinfo)) {
echo $row['membername'];
}
Obviously this doesn't work as I get the following errors:
Warning: mysql_query() expects parameter 2 to be resource, string given on line 534.
Warning: mysql_fetch_array() expects parameter 1 to be resource, null given in on line 535
While this is a very broad question and you have not provided any PHP code, you might want to break it down into various sections:
Establishing a connection to the database (with mysqli) and sending a query:
$c = mysqli_connect("localhost","user","password","db");
if (mysqli_connect_errno())
echo "Failed to connect to MySQL: " . mysqli_connect_error();
else {
$result = mysqli_query($c,"SELECT * FROM members");
while($row = mysqli_fetch_assoc($result)) {
echo "{$row['membername']}";
}
}
mysqli_close($c);
Tieing your tables together:
It is better to start off with a clear structure (including line breaks) when getting into the MySQL syntax. One way would be to have some sort of query skeleton:
SELECT tablealias.column, table2alias.field3
FROM table AS tablealias
LEFT|RIGHT|INNER JOIN table2 AS table2alias ON table.id=table2.id
WHERE (this and that = true or false, LIKE and so on...)
Breaking it down to your specific problem this would be:
SELECT Table1.`membername`, Table2.`name`, Table3.`fieldvalue`
FROM members AS Table1
LEFT JOIN customvals AS Table3 ON Table1.`id` = Table3.`userid`
LEFT JOIN customfields AS Table2 ON Table3.`fieldid` = Table2.`rank`
WHERE Table1.`Id` = 'UserID to be searched for'
Improvements & Security measures:
But there is even more to it than meets the eye. If you have just begun, you might as well dive directly into prepared mysqli- statements. Given the query to get your members, the only changing part is the ID. This can be used for a prepared statement which is much more secure than our first query (though not as fast). Consider the following code:
$sql = "SELECT Table1.`membername`, Table2.`name`, Table3.`fieldvalue`
FROM members AS Table1
LEFT JOIN customvals AS Table3 ON Table1.`id` = Table3.`userid`
LEFT JOIN customfields AS Table2 ON Table3.`fieldid` = Table2.`rank`
WHERE (Table1.`Id` = ?)";
$c = mysqli_connect("localhost","user","password","db");
$stmt = $c->stmt_init();
if ($stmt->prepare($sql)) {
$stmt->bind_params("i", $userid);
$stmt->execute();
while ($stmt->fetch()) {
//do stuff with the data
}
$stmt->close();
}
$mysqli->close();
This SQL query should do it:
SELECT a.membername, a.Id, b.fieldid, b.userid, b.fieldvalue, c.rank, c.name
FROM members AS a
LEFT JOIN customvals AS b ON a.id = b.userid
LEFT JOIN customfields AS c ON b.rank = c.fieldid
WHERE a.Id = #MEMBERIDHERE#;

Comparing two MySQL tables to populate a dropdown

I'm trying to populate a dropdown menu by comparing two tables, one has a list of supervisor and employee numbers, the other has employee numbers and names. I need to take the numbers for each supervisor and employee and turn them into employee names for the drop down menu, so basically
TABLE payroll_employeelist
Supervisor Employee
1234 3456
1234 2239
1234 123
2910 338
2910 3901
TABLE payroll_users
number name
3456 John Smith
2239 Mary Jane
123 Joe Brown
etc
Supervisors are identified by a session variable callede $usernumber.
What I have so far and is returning one result (just one!) is the following:
if ($loademployees == 1){
echo "<option value=\"base\">---- Employee Name ----</option>";
$query = "SELECT payroll_employeelist.employee, payroll_users.number, payroll_users.name FROM payroll_employeelist WHERE supervisor='$usernumber' LEFT JOIN payroll_users ON payroll_employeelist.employee=payroll_users.number ";
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
echo "<option value=\">" . $row{'name'} . "</option>";
}
echo "</select><br>";
}
Can anyone help with this? I get the feeling I've done something funny with the JOIN. It should look like a list of employee names in the dropdown.
UPDATE:
What I have now is:
if ($loademployees == 1){
echo "<option value=\"base\">---- Employee Name ----</option>";
$query = "SELECT payroll_employeelist.supervisor, payroll_employeelist.employee, payroll_users.number, payroll_users.name
FROM payroll_employeelist
INNER JOIN payroll_users
ON payroll_employeelist.employee = payroll_users.number
WHERE supervisor = '$usernumber' ";
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
echo "<option value=\">" . $row['name'] . "</option>";
}
echo "</select><br>";
}
This is successfully returning one of the three records in the test data set, just one, the middle record. The $usernumber is generated internally by the way, no injection possible.
LAST UPDATE- SOLVED
The problem believe it or not was
echo "</select><br>";
it was echoing that before echoing the results of the while loop so it thought the options list was empty. I can't explain the randomly appearing single employee mind you, but it's working now.
You need to join payroll_users twice on table payroll_employeelist since there are two columns that are dependent on it.
SELECT sup.Name SupervisorName,
empName EmployeeName
FROM payroll_employeelist a
INNER JOIN payroll_users sup
ON a.Supervisor = sup.number
INNER JOIN payroll_users emp
ON a.Employee = emp.Number
WHERE sup.Supervisor = '$usernumber'
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?
That's probably because you put the join condition inside the WHERE, but you probably meant to have it outside:
SELECT payroll_employeelist.employee, payroll_users.number, payroll_users.name
INNER JOIN payroll_users ON payroll_employeelist.employee=payroll_users.number
FROM payroll_employeelist
WHERE supervisor='$usernumber'
Also, if you use LEFT JOIN you will also get employees that are not attached to any user. A few things about escaping:
$query = "SELECT ... WHERE supervisor='$usernumber' ... ";
That's susceptible to SQL injection if $usernumber comes from a web request; consider using either mysql_real_escape_string() to escape it or switch to PDO / mysqli and use prepared statements instead.
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
echo "<option value=\">" . $row{'name'} . "</option>";
}
You should escape $row['name'] as well, and you shouldn't use curly braces either:
echo "<option value=\">" .
htmlspecialchars($row['name'], ENT_QUOTES, 'UTF-8') .
"</option>";
SELECT
tb1.supervisor,
tb1.employee,
tb2.name
FROM
payroll_employeelist AS tb1
INNER JOIN payroll_users AS tb2
ON tb1.employee = tb2.number
As you want exact matches, without non-matching values, you need INNER JOIN instead of LEFT JOIN
Use
SELECT payroll_employeelist.employee, payroll_users.number, payroll_users.name FROM payroll_employeelist LEFT JOIN payroll_users ON payroll_employeelist.employee = payroll_users.number WHERE supervisor = '$usernumber'
instead.
You should look at using PDO for your queries. Since you are dynamically assigning values into your query PDO will be a bit more secure, and if you're running this query multiple times it will be faster with PDO.
As for your query, you have your SQL Clauses ordered incorrectly. Perhaps these links will help:
PDO Tutorial from MySQL
SQL Join Tutorial
you have a mistake in your sintax
please check
$query = "SELECT payroll_employeelist.employee, payroll_users.number, payroll_users.name FROM payroll_employeelist WHERE supervisor='$usernumber' LEFT JOIN payroll_users ON payroll_employeelist.employee=payroll_users.number ";
should be
$query = "SELECT payroll_employeelist.`employee`, payroll_users.`number`, payroll_users.`name` FROM `payroll_employeelist` LEFT JOIN `payroll_users` ON payroll_employeelist.employee` = payroll_users.`number` WHERE `supervisor` = '$usernumber' ";
about this
WHERE `supervisor` = '$usernumber' ";
what table does supervisor is in? you need to fix with prefix payroll_employeelist or payroll_users
documentation here
I would like to also to remember you that mysql_ functions are deprecated so i would advise you to switch to mysqli or PDO for new projects.

Categories