Bad query - INNER JOIN - php

I am getting a bunch of undefinded index warnings when i print out my data from a SQL query, when i remove the INNER JOINS most of the warnings disappear. I am not sure what is causing that error.
My code is here:
<?php
$id = $_GET['id'];
$sql = "SELECT * FROM updates INNER JOIN clients ON updates.c_id = clients.c_id INNER JOIN pages ON updates.page = pages.p_id INNER JOIN projects ON updates.p_id = projects.p_id WHERE u_id='$id' LIMIT 1";
echo $sql;
$result = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_assoc($result);
// put update_id in hidden form and pass it to the next page
$u_id = $row['u_id'];
?>
<h4>Viewing update for <i><? echo $row['fname'] ." ". $row['lname'] ?></i> for their <i><? echo $row['p_title']; ?> project</i></h4>
<h4><b>Posted on: </b> <? echo $row['date_submitted'] = date("F j, Y, g:i a"); ?></h4>
Any idea on what I can do? The reason I have the INNER JOIN for CLIENTS is because "fname" and "lname" are stored there
clients.c_id = updates.c_id
Where I have: "p_url" "p_title" those are stored in the table PROJECTS which is also:
clients.c_id = projects.c_id
Edit with new problem
My code is here:
$sql = "SELECT
updates.u_id AS u_id,
updates.date_submitted AS date_submitted,
updates.deadline AS deadline,
updates.description AS description,
updates.priority AS priority,
pages.page_name AS page_name,
clients.fname AS fname,
clients.lname AS lname,
projects.p_url AS p_url,
projects.p_title AS p_title,
FROM updates INNER JOIN clients ON updates.c_id = clients.c_id INNER JOIN pages ON updates.page = pages.p_id INNER JOIN projects ON updates.p_id = projects.p_id WHERE u_id='$id' LIMIT 1";
The error is:
Not unique table/alias: 'clients'

Edited answer:
Ah, I incorrectly assumed it had to do with SQL indexes. It appears it's actually a PHP error, related to you trying to print out array elements that don't exist.
For all of your prints that include elements of $row ($row['deadline'], etc), you need to make sure that there are actually columns named that being returned by your query. If there's not a column named "deadline", that attempt to print it is going to generate the warning.
Edit again: since this got bumped up, I guess I'll go into a little more detail.
First of all, as bobince points out, you have SQL injection possible. The first line should be:
$id = intval($_GET['id']);
if $id will always be an integer, and mysql_real_escape_string() if it could be a string.
Second, SELECT * is generally bad form, especially in a case with joins. I don't know exactly which tables particular fields come from, but your query should look more like this, where you select only the fields you're actually going to use:
$sql = "SELECT clients.fname, clients.lname, projects.p_url, projects.p_title, updates.date_submitted ".
"FROM updates ".
"INNER JOIN clients ON updates.c_id = clients.c_id ".
"INNER JOIN pages ON updates.page = pages.p_id ".
"INNER JOIN projects ON updates.p_id = projects.p_id ".
"WHERE updates.u_id='$id' ".
"LIMIT 1";
Next, $u_id gets set to exactly the same value as $id already had, so it's kind of a pointless variable.
Finally, on the last line, you have:
<? echo $row['date_submitted'] = date("F j, Y, g:i a"); ?>
I'm not sure what you're expecting this to do, but it's going to assign date("F j, Y, g:i a"); to $row['date_submitted'] and then end up printing out "true" or "1" or something, that's probably not what you were going for.
Newest problem: You both try to select from clients, and join clients, you can't do both, at least without giving one of them an alias.

I don't think this has anything to do with the SQL (but I could be wrong). You might take a look at this thread for a start.

SELECT * FROM updates INNER JOIN clients
When you ‘SELECT *’ you get each column from both tables. Because columns can have the same names, the column names generated automatically by ‘*’ are prefixed with the table name. So your associative array will contain indexes like:
updates.u_id
clients.c_id
...
So when you try to access the array using an unprefixed column name such as 'page_name', it fails because that index isn't there.
You can use the full column name ('pages.page_name'), or you can explicitly give your own column names by saying:
SELECT updates.u_id AS u_id, pages.page_name AS page_name, ...
FROM updates JOIN client ...
u_id='$id'
Whoops, SQL injection hole. Congratulations, you are this week's 1000th winner of the obligatory xkcd link.
mysql_real_escape_string() is your friend. (Even better: mysqli parameterised queries.)
<? echo $row['deadline']; ?>
Whoops, HTML injection hole. htmlspecialchars() is your friend.

Related

Query works in phpmyadmin but same query won't return in PHP script

This is NOT a duplicate. None of the already existing threads have the same problem as me.
I have a database that stores athlete performances. It contains sessions, each session has sets, each set has "tables" (such as 4x100m, 12x50m and so on), and each table has times. I also have a table for athletes. Each athlete has an ID, each time links with the athlete through the AthleteID. Every session, set, timetable and time also have each unique IDs, used to link them with each other.
I want to make it so that when passing a session ID, it will return all the athletes that have at least 1 time in that session. I made a page that gets requests and the session ID is passed as GET search data (will make it POST later on). The request system works fine, but the problem is in the query. To do it I used inner joins to connect each table. This is my query (it is not the fastest method, but that's for another thread):
$q = "SET #evID = " . $method['sessID'] . ";";
$q .= "SELECT `athletes`.* FROM `events`
INNER JOIN `sets` ON `sets`.`EventID` = `events`.`EventID`
INNER JOIN `timetables` ON `timetables`.`SetID` = `sets`.`SetID`
INNER JOIN `times` ON `times`.`TableID` = `timetables`.`TableID`
INNER JOIN `athletes` ON `athletes`.`ID` = `times`.`AthleteID`
WHERE `events`.`EventID` = #evID
AND `times`.`TimeID` IN(
SELECT MIN(`TimeID`)
FROM `times`
WHERE `TableID` IN(
SELECT `TableID`
FROM `timetables`
WHERE `SetID` IN(
SELECT `SetID`
FROM `sets`
WHERE `EventID` = #evID
)
)
GROUP BY `AthleteID`
)";
Every single time I ran that in phpmyadmin it returned all the athletes, and the data was correct. However, when I run it in my script, the query value is false (such as if there is an error). I tried debugging like this:
$r = $db -> query($q);
var_dump($q);
var_dump($r);
var_dump($db->error);
The query is returned just fine (only difference is lack of newline characters), and when I copy what's returned in phpmyadmin the data is just the same. The rest however:
bool(false)
string(228) "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT `athletes`.* FROM `events` INNER JOIN `sets` ON `sets`.`EventID` = `...' at line 1"
Other users with the same problem have not really gone that far to find out if they're wrong, but I have. This post is not a duplicate, and I didn't find any solutions online. Could this be a problem with the amount of queries in a single string? (There is one for setting #evID and one for the actual selection). Please explain the solution and methods kindly as I'm only 13 and still learning...
As #NigelRen has suggested, please use parameterized prepared statement.
Assuming that
$sessionid is storing the value for EventID, and assuming that this variable is of integer type; and
$conn is the connection
Then for Mysqli, you can use:
//$q = "SET #evID = " . $method['sessID'] . ";";
$sql = "SELECT `athletes`.* FROM `events`
INNER JOIN `sets` ON `sets`.`EventID` = `events`.`EventID`
INNER JOIN `timetables` ON `timetables`.`SetID` = `sets`.`SetID`
INNER JOIN `times` ON `times`.`TableID` = `timetables`.`TableID`
INNER JOIN `athletes` ON `athletes`.`ID` = `times`.`AthleteID`
WHERE `events`.`EventID` = ?
AND `times`.`TimeID` IN(
SELECT MIN(`TimeID`)
FROM `times`
WHERE `TableID` IN(
SELECT `TableID`
FROM `timetables`
WHERE `SetID` IN(
SELECT `SetID`
FROM `sets`
WHERE `EventID` = ?
)
)
GROUP BY `AthleteID`
)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ii", $sessionid, $sessionid);
$stmt->execute();
$result = $stmt->get_result(); // get the mysqli result
$row = $result->fetch_assoc(); // fetch data
// do other things you want , such as echo $row['fieldname1'];

Current selection does not contain a unique column. Mysqli. Duplication?

I can't seem to select/retrieve the "Package Table" and merge it into 1 table that contains the other table which is "Events Table". I don't know what seems to be the problem though.
Whenever i tried to execute my query and the only thing that pops up is the
events_ table, the Package table on the other hand does not. I tried another another simple query,
SELECT * FROM event_table JOIN package ON event_id WHERE cusact_id = 8 AND event_id=80
And the query works fine.
Event Table (Structure):
http://prntscr.com/gbr6vr
Package Table (Structure):
https://prnt.sc/gbr793
Note: I have a column named package_id on events_table and package. Is that the problem? Im sorry, still new to mysql.
side note:
$c_id = $_SESSION['u_id'];
$n_id = $_GET['n_id'];
$p_id = $_GET['new_p_id'];
all of these has data, so no problem here.
Here is my query:
<?php
session_start();
include_once 'order.confirmation-header.php';
include 'includes/dbh.inc.php';
$c_id = $_SESSION['u_id'];
$n_id = $_GET['n_id'];
$p_id = $_GET['new_p_id'];
$sql = "
SELECT event_id, event_name, event_date, event_time_start,
event_time_end, cusact_id, theme, reserve_date, reserve_time
FROM event_table as e
INNER JOIN package as p
ON e.package_id = p.package_id
WHERE cusact_id = $c_id AND event_id=$n_id
";
$data = mysqli_query($conn, $sql);
if(!$data){
echo("Error description: " . mysqli_error($conn));
}
You aren't requesting any of the package columns (by merge the table I assume you mean retrieve a record set)
SELECT event_id, event_name, event_date, event_time_start,
event_time_end, cusact_id, theme, reserve_date, reserve_time, p.*
FROM event_table as e
INNER JOIN package as p
ON e.package_id = p.package_id
WHERE cusact_id = $c_id
AND event_id=$n_id
Your code is wide open to SQL injection, and I'd really consider using the PDO API with a prepared statement.

Why do i double my display in json

So i fetch my data from two tables in my php and encode it in one json object. I got everything i needed except that it doubles the display. And my teamone is located in the matches tables. instead of starting from array 0, it starts after the schedules tables. Which is array 7. I dont know why this happen.
Here is my php.
$sql = "SELECT * from schedule, matches;";
$con = mysqli_connect($server_name,$mysql_user,$mysql_pass,$db_name);
$result = mysqli_query($con,$sql);
$response = array();
while($row=mysqli_fetch_array($result))
{
array_push($response, array("start"=>$row[4],"end"=>$row[5],"venue"=>$row[6], "teamone"=>$row[8], "teamtwo"=>$row[9],
"s_name"=>$row[17]));
}
echo json_encode (array("schedule_response"=>$response));
mysqli_close($con);
?>
Here is my display. As you can see there are four displays but in my database it only has 2. It doubles the display. How do i fix this? Thanks
{ "schedule_response":[
{"start":"2016-11-10 00:00:00","end":"2016-11-04 00:00:00","venue":"bbbb","teamone":"aaa","teamtwo":"bbb",
"s_name":"hehehe"},
{"start":"2016-11-23 00:00:00","end":"2016-11-24 00:00:00","venue":"bbbbbbbb","teamone":"aaa","teamtwo":"bbb",
"s_name":"hehehe"},
{"start":"2016-11-10 00:00:00","end":"2016-11-04 00:00:00","venue":"bbbb","teamone":"ehe","teamtwo":"aha",
"s_name":"aaa"},
{"start":"2016-11-23 00:00:00","end":"2016-11-24 00:00:00","venue":"bbbbbbbb","teamone":"ehe","teamtwo":"aha",
"s_name":"aaa"}]}
I need to get the teamone, teamtwo and s_name values from the matches while i need the start, end and the venue from the schedule table in one query.
Schedule table
Matches Table
Because of your SQL query, you should not forget to perform some form of a grouping (the way you select results from both table defines that):
$sql = "SELECT * from schedule s, matches m GROUP BY s.id"; //I assume that your table schedule has an `id`
Or, you can rework the query to be more readable:
$sql = "SELECT s.*, m.* FROM schedule s
INNER JOIN matches m ON m.schedule_id = s.id
GROUP BY s.id"; //I assume that you have such database design that you have defined foreign key on table `matches`.
Of course, the INNER JOIN above could be LEFT OUTER JOIN - it all depends on your database design.
I think it is the problem with mysqli_fetch_array().
Can you please change mysqli_fetch_array() to mysqli_fetch_assoc()

PHP/MySQL select query issues

I was wondering if anyone could give me a hand. I currently have 3 tables as follows:
users(user_id, username, first_name, last_name, password)
module(module_id, name, crn)
userModule(user_id, module_id)
What would be the best way to access this? From doing basic research it looks like a RIGHT JOIN would be appropriate...
How would I go about looking at the modules table based on the user_id variable?
I gave it ago here but it doesn't seem to work.
$result = mysql_query("SELECT * FROM module JOIN userModule ON (module.module_id = userModule.module_id) JOIN users ON (userModule.user_id = users.user_id) WHERE user_id = 2");
$row = mysql_fetch_row($result);
echo $row[0];
echo $row[1];
echo $row[2];
$result = mysql_query("SELECT * FROM modules LEFT JOIN userModule ON userModule.module_id = modules.module_id WHERE userModule.user_id = 2");
It should work!
Better yet, if you only want to get modules info:
SELECT modules.* FROM modules ....
I used LEFT JOIN but there are several other methods : RIGHT JOIN, INNER JOIN or FULL JOIN. See what's the difference between those methods here: http://www.w3schools.com/sql/sql_join.asp
Also, you should always add " or die(mysql_error());" after your mysql_query(). If the query is wrong (bad formatting, miswritten fields, etc.) it will print a useful error.

mysql php join statement

I am not sure if that join statement is writen in the right way:
<?php
function generateComment($commentID)
{
$avatar_Q=mysql_query("
SELECT * FROM comments com
INNER JOIN users us ON com.user_id=us.user_id
WHERE comment_id=$commentID // will that $commentID be red in that query string or will it treat it as a string "commentID"
");
if($row=mysql_fetch_array($avatar_Q))
{
$userName=$row["us.user_name"]; // do I refer to the fields like that
$avatarPath=$row["us.avatar"];
$avatarRep=$row["us.reputation"];
$message=$row["com.comment"];
$date=$row["com.date"];
}
mysql_close();
if(!isset($avatarPath))
{
$avatarPath="blank picture";
}
?>
Is this the most efficient way to write a join statement
Your query is written correctly, but you can improve it by specifing the table on comment_id, and for a better returning I suggest you to specify with column you want back, also I will use the variable outside the "string", because it's a numeric value (I suppose you omit the single quote like...
$sql = "Select com.command_it, etc
FROM ..... WHERE com.comment_id = ".$commentID."";
If otherwise the com.comment_id is text or varchar you must use the single quote like:
$sql = "Select com.command_it, etc
FROM ..... WHERE com.comment_id = '".$commentID."'";
Moreover this way you get only the rows where there is a user and a comment, if one user have no comment you don't retrieve that user...
If you want the user also if he has no comments you must use a LEFT JOIN
$sql = "SELECT com.comment_id, etc FROM users us
LEFT JOIN comments com ON com.user_id=us.user_id
WHERE com.comment_id=".$commentID."";
Not sure what you're doing with this line
WHERE comment_id=$commentID // will that $commentID be red in that query string or will it treat it as a string "commentID"
");
But you need to specify which table comment_id is coming from, say comments, then you might do something like
$avatar_Q=mysql_query("SELECT * FROM comments com
INNER JOIN users us ON com.user_id=us.user_id
WHERE com.comment_id=$commentID");
Not sur if it's the best way, but you could try to mysqlslap a mysql DB with it. Compare it with left join and other types of join and see which one is the best in your case. MySQL is all about slapping.

Categories