select with join using a standard php function - php

Im trying to use a php function to select data from a database, Im using a "standard" php function:
function select($table, $where, $other=''){
try{
$a = array();
$w = "";
$other=" ".$other;
foreach ($where as $key => $value) {
$w .= " and " .$key. " like :".$key;
$a[":".$key] = $value;
}
$stmt = $this->bd->prepare("select * from ".$table." where 1=1 ". $w.$other);
$stmt->execute($a);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if(count($rows)<=0){
$reponse["statut"] = "warning";
$reponse["message"] = "no data found.";
}else{
$reponse["statut"] = "Success";
$reponse["message"] = "Success";
}
$reponse["data"] = $rows;
}catch(Exception $e){
$reponse["statut"] = "Error";
$reponse["message"] = 'selection failed: ' .$e->getMessage();
$reponse["data"] = null;
}
return $reponse;
}
The function works satisfyingly I faced problems only when I aimed to use a join and selecting from two tables.
say we have these two tables:
id-cat | cat-name |
1 | aaaaaa |
2 | aaadda |
3 | saaaca |
4 | ahhaaa |
and
id-cat | sub-cat |
1 | 2 |
1 | 3 |
1 | 4 |
2 | 3 |
2 | 4 |
How to select the a category's subs name with given id-cat using MY FUNCTION ??

You just need a simple LEFT JOIN to the second table, using the column that exists in both tables.
$stmt = $this->bd->prepare("SELECT *
FROM $table
LEFT JOIN $table2 USING id-cat
WHERE 1=1 ". $w.$other);

Related

Get data and insert it using loop (MSQL/I)

I select data from table A and what I want is to insert that data using a loop.
Here's my code:
$getlvls = "SELECT * FROM `access_chart` WHERE `ac_id`='$data->ac_id'";
$qry99 = $con->query($getlvls);
while($row = $qry99->fetch_assoc()) {
$lvl1 = $row['lvl1'];
$lvl2 = $row['lvl2'];
$lvl3 = $row['lvl3'];
$lvl4 = $row['lvl4'];
}
for($jaa = 1; $jaa <=4; $jaa++){
$auth_id = '$lvl'+$jaa;
$sql1 = "INSERT INTO `overtime_log`(`ot_id`, `lvl`, `user_id`) VALUES('$ot_id', $jaa, '$auth_id')";
$qry = $con->query($sql1);
}
I don't include all of my codes. Everything works, except for inserting the column $lvl1, $lvl2, $lvl3 and $lvl4 using a loop. Or if you would suggest other logic that's find.
Thanks in advance.
EDITED
Select the data:
|----------------|
|--access_chart--| TABLE
|----------------|
-------------------
|---------|---------------|--------|--------|--------|--------|
|--ac_id--|--access_name--|--lvl1--|--lvl2--|--lvl3--|--lvl4--|
|---------|---------------|--------|--------|--------|--------|
| 1 | MIS Dept | 4 | 5 | 9 | 0 |
This might be the output after INSERT QUERY:
|----------------|
|--overtime_log--| TABLE
|----------------|
-------------------
|---------|-------|-----------|
|--ot_id--|--lvl--|--user_id--|
|---------|-------|-----------|
| 1 | 1 | 4 |
| 1 | 2 | 5 |
| 1 | 3 | 9 |
| 1 | 4 | 0 |
Not sure where $ot_id is defined, but assuming you're using only ids and SQL injection isn't a concern, you could use something like:
$getlvls = "SELECT * FROM `access_chart` WHERE `ac_id`='$data->ac_id'";
$qry99 = $con->query($getlvls);
while($row = $qry99->fetch_array())
{
foreach(array(1=>$row['lvl1'],2=>$row['lvl2'],3=>$row['lvl3'],4=>$row['lvl4']) as $key=>$lvl)
{
$sql1 = "INSERT INTO `overtime_log`(`ot_id`, `lvl`, `user_id`) VALUES('$ot_id', $key, '$lvl')";
$qry = $con->query($sql1);
}
}
Alternatively you could avoid the inner loop altogether and just write the INSERT using multiple-insert syntax:
$getlvls = "SELECT * FROM `access_chart` WHERE `ac_id`='$data->ac_id'";
$qry99 = $con->query($getlvls);
while($row = $qry99->fetch_array())
{
$con->query("INSERT INTO `overtime_log`(`ot_id`, `lvl`, `user_id`)
VALUES('$ot_id', 1, '{$row['lvl1']}'),
('$ot_id', 2, '{$row['lvl2']}'),
('$ot_id', 3, '{$row['lvl3']}'),
('$ot_id', 4, '{$row['lvl4']}')");
}

Dynamic HTML table - Updating cell rows

I have an HTML table being dynamically generated from database. The solution for achieving this can be seen at this question Adding rows to a HTML table with dynamic columns.
This works fine, except I want to indicate all sessions a person attended for each week in the same row - with the code below, an additional session attendance becomes another row appended to the HTML table. So what I want is like:
DB tables are like ('week', 'cohort' and 'attendance' tables)
+---------+-----------+----------+-----------+
| week_pk | week_name | sessions | cohort_fk |
+---------+-----------+----------+-----------+
| 1 | Week 1 | 3 | 1 |
| 2 | Week 2 | 2 | 1 |
| 3 | Week 3 | 1 | 1 |
+---------+-----------+----------+-----------+
+-----------+-------------+-------------+-------------+
| cohort_pk | cohort_name | cohort_code | cohort_year |
+-----------+-------------+-------------+-------------+
| 1 | Some name | MICR8976 | 2014 |
+-----------+-------------+-------------+-------------+
+---------------+-----------+-------------+---------+-----------+---------+---------+
| attendance_pk | person_id | given_names | surname | cohort_fk | week_fk | session |
+---------------+-----------+-------------+---------+-----------+---------+---------+
| 1 | 123456 | Bill | Smith | 1 | 1 | 2 |
| 2 | 123456 | Bill | Smith | 1 | 2 | 2 |
| 3 | 753354 | Fred | Jones | 1 | 1 | 1 |
| 4 | 753354 | Fred | Jones | 1 | 2 | 1 |
| 5 | 753354 | Fred | Jones | 1 | 3 | 1 |
+---------------+-----------+-------------+---------+-----------+---------+---------+
And the code that I'm using:
$cohort = $_POST['cohort'];
$year = $_POST['year'];
$query = "SELECT * FROM cohort, week
WHERE week.cohort_fk = cohort.cohort_pk
AND cohort.cohort_year = '$year'
AND cohort.cohort_pk = '$cohort'
ORDER BY week.week_pk";
$result = mysql_query($query, $connection) or die(mysql_error());
echo "<table width='100%' cellpadding='4' cellspacing='0' class='attendance_table'>";
echo "<tr><td class='theadings'></td>";
$second_row = "<tr><td class='theadings'></td>";
$totalcolumn = 1;
while( $row = mysql_fetch_assoc($result) ){
$weekname = $row["week_name"];
$n_session = $row["sessions"];
$weekpk = $row["week_pk"];
$totalcolumn += $n_session;
echo "<td class='theadings' colspan='$n_session'>$weekname</td>";
for($i=1; $i<=$n_session; $i++){
$second_row .= "<td class='theadings_lab'>Lab $i</td>";
$weeksession[$weekpk][$i] = $totalcolumn - $n_session + $i;
}
}
echo "</tr>";
echo $second_row . "</tr>";
$query = "SELECT * FROM cohort, week, attendance
WHERE week.cohort_fk = cohort.cohort_pk
AND attendance.week_fk = week.week_pk
AND attendance.cohort_fk = cohort.cohort_pk
AND cohort.cohort_year = '$year'
AND cohort.cohort_pk = '$cohort'
ORDER BY attendance.attendance_pk";
$result = mysql_query($query, $connection) or die(mysql_error());
while( $row = mysql_fetch_assoc($result) ){
$name = $row["given_names"] . " " . $row["surname"];
$weekpk = $row["week_pk"];
$sno = $row["session"];
echo "<tr><td class='tborder_person_left'>$name</td>";
for($i=2; $i<=$totalcolumn; $i++){
if( $weeksession[$weekpk][$sno] == $i )
echo "<td class='tborder_person_attended'>&#10004</td>";
else
echo "<td class='tborder_person'>-</td>";
}
echo "</tr>";
}//end while
echo "</table>";
#Kickstart below is an example of what the table looks like with your code. You can see for example Melody Chew and Kit Yeng Melody Chew (same person) have two seperate rows. The unique identifier needs to be on the person_id which exists in the attendance table (apologies for not showing this before! my BAD Note also the additional columns on the right of the table with the crosses which should be under the week 2 column.
I personally would go through nested arrays.
I give you an example. Note that this is only in principle, as I do not have the database, I have not tested. :)
1 -> statement of the array $liste_name = array();
2 -> Replace your second treatment by :
while( $row = mysql_fetch_assoc($result) ){
$name = $row["given_names"] . " " . $row["surname"];
$weekpk = $row["week_pk"];
$sno = $row["session"];
$person_id = $row["person_id"]; //add person_id
$liste_name[$person_id] = $name; // to have the last name
$tab[$person_id][1] = "<td class='tborder_person_left'>$name</td>"; // to have the last name
for($i=2; $i<=$totalcolumn; $i++){
if( $weeksession[$weekpk][$sno] == $i )
$tab[$person_id][$i] = "<td class='tborder_person_attended'>&#10004</td>";
}
}//end while
3 -> Fill the empty areas :
foreach ($liste_name as $person_id => $name){
$tab2[$person_id][1] = $tab[$person_id][1];
for($i=2; $i<=$totalcolumn; $i++){
if (!isset($tab[$person_id][$i]) || ($tab[$person_id][$i] != "<td class='tborder_person_attended'>&#10004</td>"))
$tab[$person_id][$i] = "<td class='tborder_person'>-</td>";
$tab2[$person_id][$i] = $tab[$person_id][$i];
}
}
4 -> Use the array :
foreach($tab2 as $person_id => $col){
echo "<tr>";
foreach ($col as $i => $value){
echo $value;
}
echo "</tr>";
}
echo "</table>";
I try with fictional data and it works. :)
I would be tempted to use a couple of CROSS JOINs to get all the possible combinations of session / week / person, and then left join that against attendance.
SELECT unique_names.given_names,
unique_names.surname,
week_sessions.week_pk,
week_sessions.session,
attendance.attendance_pk
FROM
(
SELECT week_pk, sub1.i AS session, week_name, week.cohort_fk, cohort.cohort_year
FROM week
INNER JOIN cohort
ON week.cohort_fk = cohort.cohort_pk
INNER JOIN
(
SELECT 1 i UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10
) sub1
ON week.sessions >= sub1.i
WHERE cohort.cohort_year = 2014
AND cohort.cohort_pk = 1
) week_sessions
CROSS JOIN
(
SELECT DISTINCT given_names, surname
FROM attendance
) unique_names
LEFT OUTER JOIN attendance
ON week_sessions.week_pk = attendance.week_fk
AND week_sessions.cohort_fk = attendance.cohort_fk
AND week_sessions.session = attendance.session
AND unique_names.given_names = attendance.given_names
AND unique_names.surname = attendance.surname
ORDER BY unique_names.given_names,
unique_names.surname,
week_sessions.week_pk,
week_sessions.session
I have knocked up an SQL fiddle for this:-
http://www.sqlfiddle.com/#!2/4a388/7
You can then loop around this easily (although adding the titles is a bit messy - following would be half the size without the titles). I have used the mysql_* functions as that is what you are already using.
<?php
$connection = mysql_connect("localhost", "root", "") or die(mysql_error());
mysql_select_db("test_area") or die(mysql_error());
$sql = "SELECT unique_names.person_id,
unique_names.FullName,
week_sessions.week_pk,
week_sessions.session,
attendance.attendance_pk
FROM
(
SELECT week_pk, sub1.i AS session, week_name, week.cohort_fk, cohort.cohort_year
FROM week
INNER JOIN cohort
ON week.cohort_fk = cohort.cohort_pk
INNER JOIN
(
SELECT 1 i UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10
) sub1
ON week.sessions >= sub1.i
WHERE cohort.cohort_year = 2014
AND cohort.cohort_pk = 1
) week_sessions
CROSS JOIN
(
SELECT person_id, MAX(CONCAT_WS(' ', given_names, surname)) AS FullName
FROM attendance
GROUP BY person_id
) unique_names
LEFT OUTER JOIN attendance
ON week_sessions.week_pk = attendance.week_fk
AND week_sessions.cohort_fk = attendance.cohort_fk
AND week_sessions.session = attendance.session
AND unique_names.person_id = attendance.person_id
ORDER BY unique_names.person_id,
unique_names.FullName,
week_sessions.week_pk,
week_sessions.session";
$result = mysql_query($sql, $connection) or die(mysql_error());
$prev_person_id = 0;
$first = true;
$header = array('Name'=>array('Session'));
$output = array();
while( $row = mysql_fetch_assoc($result) )
{
if ($prev_person_id != $row['person_id'])
{
if ($prev_person_id != 0)
{
$first = false;
}
$prev_person_id = $row['person_id'];
$output[$prev_person_id] = array();
}
if ($first)
{
$header["Week ".$row['week_pk']]["S".$row['session']] = "S".$row['session'];
}
$output[$prev_person_id][] = (($row['attendance_pk'] == '') ? ' ' : 'X');
}
$header1 = '';
$header2 = '';
foreach($header as $key=>$value)
{
$header1 .= "<td colspan='".count($value)."'>$key</td>\r\n";
foreach($value as $key1=>$value1)
{
$header2 .= "<td>$value1</td>\r\n";
}
}
echo "<table border='1'>\r\n";
echo "<tr>\r\n$header1</tr>\r\n";
echo "<tr>\r\n$header2</tr>\r\n";
foreach($output as $name=>$value)
{
echo "<tr><td>$name</td>";
foreach($value as $key1=>$value1)
{
echo "<td>$value1</td>\r\n";
}
echo "</tr>";
}
echo "</table>\r\n";
?>

PHP SQL query in while loop JOIN

I'm making a basic notification system for a practice project. I have several tables, two of which look something like the following:
> Table 1: "Users"
>
userid | username | Firstname | Lastname
1 | Daffy | Daffy | Duck
2 | Flinstone | Fred | Flinstone
3 | dduck | Donald | Duck
>
> Table 2: "Notifications"
>
Notification_id | from_user_id | to_user_id | SeenOrUnseen | type
1 | 1 | 2 | 1 | fRequest
> 2 | 1 | 2 | 0 | comment
> 3 | 1 | 2 | 1 | comment
> 4 | 3 | 1 | 1 | fRequest
> 5 | 2 | 3 | 1 | fRequest
> 6 | 2 | 3 | 0 | comment
> 7 | 3 | 2 | 0 | comment
I then need data from both these tables, and would normally JOIN the tables on the user_id and from_user_id before sending of an sql query. However, a join seems to return multiple values because in the second table there are multiple instances of from_user_id. Instead, i'm querying the database, returning the data in a while loop, and within that while loop sending out another query to the database for a different tables' information:
include('../../db_login.php');
$con = mysqli_connect("$host", "$username", "$password", "$db_name");
$tbl_name = "Profile";
$tplname = "profile_template.php";
$tplname2 = "public_profile_template.php";
$myid = $_SESSION['identification'];
//CHECK CONNECTION
if(mysqli_connect_errno($con)) {
echo "failed to connect" . mysql_connect_error();
}else {
$result = mysqli_query($con, "SELECT * FROM Notifications WHERE to_user_id='$myid'");
$count = mysqli_num_rows($result);
if($count == 0){
$style = "display:none;";
} else {
echo "<ul class='notifications'>";
while($row = mysqli_fetch_array($result)){
$from_user_id = $row['from_user_id'];
$to_user_id = $row['to_user_id'];
$seen = $row['seen'];
$nature = $row['nature'];
$result2 = mysqli_query($con, "SELECT * FROM users WHERE id='$from_user_id'");
$count2 = mysqli_num_rows($result2);
if($count2 != 0){
while($row2 = mysqli_fetch_array($result2)){
$fromFirstname = $row2['Firstname'];
$fromLastname = $row2['Lastname'];
}
if($nature == 'fRequest'){
echo "<li> You have received a friend request from" . $fromFirstname . " " . $fromLastname . "</li>";
}
}
}
echo "</ul>";
}
mysqli_close($con);
}
echo "<div id='NoNotification'></div>";
echo "<div id='Notification' style='" . $style . "'></div>";
?>
Is there a better way of doing this?
Thanks for any help!
You can do something like this:
SELECT n.*, u.*
FROM Notifications n
JOIN users u ON n.from_user_id=u.id
WHERE n.to_user_id=$myid
ORDER BY n.id, u.id
You will get all the data you need. The notification data and the user data. It is better to define which fields you want to retrieve in stead of * so you got a better view of what your using and your not sending data which you don't use.
Als you are using an integer (id) as a string, you can just put the $myid there. Also beaware this is not a safe query for MySQL injection. For more info.

How to get the right output from this SELECT query?

I have a query like so:
SELECT * FROM `purchases` p
JOIN `purchase_types` pt ON p.purchase_type = pt.node
When I run it in PHPmyAdmin it returns the proper result set like so:
node | purchase_type | amount_spent | node | name
--------------------------------------------------
2 | 5 | 8.5000 | 5 | Lunch
3 | 5 | 1.5000 | 5 | Lunch
4 | 6 | 4.6600 | 6 | Dinner
This is my PHP code:
$sql = "SELECT * FROM `purchases` p
JOIN `purchase_types` pt ON p.purchase_type = pt.node";
$query = mysql_query($sql);
$result = mysql_fetch_assoc($query);
$purchases = array();
while($row = mysql_fetch_assoc($query)) {
$purchases[] = array(
'name' => $row['name'],
'amount_spent' => $row['amount_spent']
);
}
for eaching over $expenses returns the following output:
3 | 5 | 1.5000 | 5 | Lunch
4 | 6 | 4.6600 | 6 | Dinner
What happens to the first "Lunch"? How can I have the PHP output be the same as the direct MySQL query output?
You call mysql_fetch_accoc before while. Don't.
You should also realize that ext/mysql will be deprecated and upgrade your code to use properly parameterized queries with PDO or mysqli
try with mysql_fetch_array,
$purchases = array();
while($row = mysql_fetch_array($query)) {
$purchases[] = $row;
}
if you want to get data just do
foreach($purchases as $key => $value)
{
$name = $value['name'];
$amount_spent = $value['amount_spent'];
echo 'name : '.$name.' , amount spent '.$amount_spent.'<br />';
}

get the column name where the data was found in MySQL

is it possible to get the Column name where a particulare data was found without looping through the result, maybe by PDO? or is there another way to do this in mySQL?
the example show only 3 columns but for my table i may have up to 30 columns need to be check
if i have a table, table1 and want to find the column(s) where 'x' was found
+----+------+------+------+
| id | Col1 | Col2 | Col3 |
+----+------+------+------+
| 0 | x | b | x |
| 1 | x | x | f |
| 2 | d | x | g |
| 3 | h | j | k |
+----+------+------+------+
currentyl i run a Select then loop to each row and check each row column if data is 'x'
$query= "SELECT * FROM table1 WHERE (Col1='x' OR Col2='x' OR Col3='x')"
$result=mysql_query($query);
$foundCols = array();
$rowCnt = 0;
while ($row = mysql_fetch_assoc($result)) {
$tmpArr = array();
if ($row['Col1'] == 'x') {
$tmpArr[] = 'Col1';
}
if ($row['Col2'] == 'x') {
$tmpArr[] = 'Col2';
}
if ($row['Col3'] == 'x') {
$tmpArr[] = 'Col3';
}
$foundCols[$rowCnt] = $tmpArr;
$rowCnt = $rowCnt+1
}
thank you
Try this:
while ($row = mysql_fetch_assoc($result)) {
...
foreach (array('Col1', 'Col2', 'Col3') as $key) {
if ($row[$key] == 'x') {
$tmpArr[] = $key;
}
}
...
}

Categories