I'm building a job search site and I have 3 tables.
1: jobs_table: id, user_id, job_title, location, job_description, currency, salary, salary_type, employment_type, post_time, visiblity
2: applications_table: id, creator_id, applicant_id, job_id, status
3: user_table: id, profile_picture, first_name, last_name, phone_number, email_address, password, data, verification_key, modify_date
Currently, I'm selecting from the jobs_table based on user input (PHP code below), however, I'm trying to also display to the user which jobs they have already applied for and to do this I need to select from the Jobs_table (get the jobs data as I'm already doing), but also select from the applications_table with the current users ID to check if there is a row with the applicant_id and job_id if this row exists then the user has already applied for that position.
Any help is much appreciated.
PHP
$conditions = [];
// Start by processing the user input into a data structure that can be used to construct the query
if (!empty($t)) {
$conditions[] = [
['job_title', 'LIKE', '%' . $t . '%'],
];
}
if (!empty($l)) {
$conditions[] = [
['location', '=', $l],
];
}
if (!empty($s)) {
$conditions[] = [
['salary', '>=', $s],
];
}
// Loop the conditions and process them into valid SQL strings
$bindValues = [];
$whereClauseParts = [];
foreach ($conditions as $conditionSet) {
$set = [];
foreach ($conditionSet as $condition) {
list($fieldName, $operator, $value) = $condition;
$set[] = "`{$fieldName}` {$operator} :{$fieldName}";
$bindValues[$fieldName] = $value;
}
$whereClauseParts[] = implode(' OR ', $set);
}
$statement = "SELECT * FROM 001_jobs_table_as WHERE visiblity = 2";
if (!empty($whereClauseParts)) {
$statement .= " AND (" . implode(') AND (', $whereClauseParts) . ")";
}
/* Pagination Code starts */
$per_page_html = '';
$page = 1;
$start=0;
if(!empty($_GET["page"])) {
$page = $_GET["page"];
$start=($page-1) * ROW_PER_PAGE;
}
$limit=" limit " . $start . "," . ROW_PER_PAGE;
$pagination_statement = $dbh->prepare($statement);
$pagination_statement->execute($bindValues);
$row_count = $pagination_statement->rowCount();
if(!empty($row_count)){
$per_page_html .= "<div class='page_row_selector'>";
$page_count=ceil($row_count/ROW_PER_PAGE);
if($page_count>1) {
for($i=1;$i<=$page_count;$i++){
if($i==$page){
$per_page_html .= '<input type="submit" name="page" value="' . $i . '" class="btn-page active_page" />';
} else {
$per_page_html .= '<input type="submit" name="page" value="' . $i . '" class="btn-page" />';
}
}
}
$per_page_html .= "</div>";
}
$query = $statement.$limit;
$pdo_statement = $dbh->prepare($query);
$pdo_statement->execute($bindValues);
$result = $pdo_statement->fetchAll();
if(empty($result)) { ?>
<div class="job_card">
<h1 class="display-5 text-center no_result_message"> No match found. </h1>
</div>
<?php }else{
foreach($result as $row) {
$user_id = $row['user_id'];
$job_key = $row['id'];
$job_title = $row['job_title'];
$location = $row['location'];
$job_description = $row['job_description'];
$employment_type = $row['employment_type'];
$salary = $row['salary'];
$salary_type = $row['salary_type'];
$currency = $row['currency'];
$post_time = $row['post_time'];
$user_id = $row['user_id'];
$to_time = time();
$from_time = strtotime($post_time);
$time_elapsed = $to_time - $from_time;
$seconds = round(abs($time_elapsed));
$minutes = round(abs($time_elapsed) / 60);
$hours = round(abs($time_elapsed) / 3600);
$days = round(abs($time_elapsed) / 86400);
$weeks = round(abs($time_elapsed) / 604800);
// display job information in here.
} ?>
UPDATE:
I have now revised my SELECT query to the following:
$statement = "SELECT * FROM 001_jobs_table_as jt";
$statement .= " LEFT JOIN 001_application_table_as at ON at.job_id = jt.jt_id";
$statement .= " RIGHT JOIN 001_user_table_as ut ON ut.id = at.applicant_id";
$statement .= " WHERE jt.visiblity = 2";
However, I'm getting duplicates in the results, every user that applies for a job duplicates that job in the results.
What about using LEFT JOIN?
The LEFT JOIN keyword returns all records from the left table
(table1), and the matched records from the right table (table2).
SELECT *, id AS jt_id FROM jobs_table jt
LEFT JOIN applications_table at ON jt.jt_id = at.job_id AND jt.user_id = at.applicant_id
WHERE jt.visibility = 2 AND (jt.job_title LIKE :job_title) AND (jt.location = :location) AND (jt.salary >= :salary);
This should return all rows from jobs_table which match searched criteria and some of those rows can have extra data from applications_table if user already applied to that specific job (row) from jobs_table.
Something like:
jt_id user_id job_title location ... id applicant_id job_id
=================================================================
1 15 php dev london
2 23 java dev liverpool
3 44 haskell manchester
4 52 front end bristol 7 52 4
5 66 golang leeds
Row with jt_id = 4 has some extra values meaning user already applied to that job.
This should give you some directions but unfortunatelly, i didn't have a time to test this query.
EDIT
I've made a mistake. LEFT JOIN should go before WHERE clause...silly me. Check the query once again, it has been updated.
Or try it online
Related
I am building an android app that uses geo location. I am trying to improve my overall app to improve its smoothness while running. I am using volly to connect to a php page on my web sever where the php page can then access my phpmyadmin database. My php page for updating locations is a horrible mess and I was hoping it can be fixed with the right sql query.
Lets get down to it.
So I have a table named users
and a table named friends
In this particular example david is friends with mark and jack. Also to clarify mark and jack are friends with david.
What I need to do is Write a query if given a user ID say for example 3 that will produce a table of that person and his friends ID, cordsV1, cordsV2 without any duplicate IDs in the table.
I was able to get this to work with using loops and variables ect but as I said it is a horrible mess.
Here is my current all sql query attempt:
SELECT DISTINCT ID, cordsV1, cordsV2 FROM `friends`,`users` WHERE user_one_ID = 1 AND status = 1;
HOWEVER this just returns all of the user IDs from the user table. I am really bad with sql so if someone could point me in the right direction it would be much appreciated.
Here is my horrible mess of code if you were wondering:
<?php error_reporting(E_ALL | E_STRICT); ?>
<?php
$THIS_USER_ID = $_GET['THIS_USER_ID'];
try {
$one = 1;
$db = new PDO("");
$sql = "SELECT * FROM friends WHERE user_one_ID = '" . $THIS_USER_ID . "' AND status = '" . $one . "' OR user_two_ID = '" . $THIS_USER_ID . "' AND status = '" . $one . "'";
$rows = $db->query($sql)
->fetchAll(PDO::FETCH_ASSOC);
$printMe = [];
foreach($rows as $row){
$printMe[] = $row;
}
$jsonArr = json_encode($printMe);
$characters = json_decode($jsonArr, true);
// Getting the size of the sample array
$size = sizeof($characters);
$neg = -1;
$sql2 = "SELECT * FROM users WHERE ID = '" . $neg . "'";
$sql3 = "";
$sql4 = "";
for ($x = 0; $x < $size; $x++ ){
if ($characters[$x]['user_one_ID'] == $THIS_USER_ID && $characters[$x]['status'] == 1){
$hold = $characters[$x]['user_two_ID'];
$sql3 = $sql3 . " OR ID = '" . $hold . "'";
} else if($characters[$x]['user_two_ID'] == $THIS_USER_ID && $characters[$x]['status'] == 1) {
$hold = $characters[$x]['user_one_ID'];
$sql4 = $sql4 . " OR ID = '" . $hold . "'";
}
}
$sql5 = $sql2 . $sql3 . $sql4;
$sql7 = "SELECT * FROM users WHERE ID = '" . $THIS_USER_ID . "'";
$printMe2 = [];
$rows3 = $db->query($sql7)
->fetchAll(PDO::FETCH_ASSOC);
foreach($rows3 as $row3){
$printMe2[] = $row3;
}
$rows2 = $db->query($sql5)
->fetchAll(PDO::FETCH_ASSOC);
foreach($rows2 as $row2){
$printMe2[] = $row2;
}
$jsonArr2 = json_encode($printMe2);
echo $jsonArr2;
$db = null;
} catch(PDOException $ex) {
die(json_encode(array('outcome' => false, 'message' => 'Unable to connect')));
}
?>
Get the user-data
SELECT
*
FROM
users
WHERE ID = ?
Get the user-data of friends
SELECT
users.*
FROM
friends
JOIN
users ON users.ID = friends.user_two_ID
WHERE
friends.user_one_ID = ?
Better use prepared statements, or your app wont be alive very long due to SQL-Injections.
You also want to have a look at meaningful names.
I have 2 tables. Table 1 is a schedule which holds weekly games. Table 2 is a separate table where you select just one team from the scheduled games for a week.
I am trying to get the difference in the score for the game that I chose a team for. So for a specific week, there are 13-16 games. I select 1 team from one of those games. If the team I pick wins, the result is the difference in the score. So if my team wins and the score is 27-10, I show 17 point. I have tried every way I can think to get this, but the best I seem to come up with is that it will calculate the last game of the week only, not the specific game that my team is involved in. The gameID is the key between both tables. Is it possible to do this? I thought by grabbing the values based on gameID from the array it would match it to the gameID associated with the selection from table 2.I am able to display the correct team, week by week, but not get the point differential for that specific game. Any ideas?
<?php
for($wk=1;$wk<=17;$wk++){
$allScoresIn = true;
$currentDT = date('Y-m-d H:i:s');
//get array of games
$games = array();
$sql = "select s.*, (DATE_ADD(NOW(), INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR) > gameTimeEastern or DATE_ADD(NOW(), INTERVAL " . SERVER_TIMEZONE_OFFSET . " HOUR) > '" . $cutoffDateTime . "') as expired ";
$sql .= "from " . DB_PREFIX . "schedule s ";
$sql .= "where s.weekNum = " . $wk . " ";
$sql .= "order by s.gameTimeEastern, s.gameID";
$query = $mysqli->query($sql);
if ($query->num_rows > 0) {
$e = 0;
$homePtDiff = 0;
$visitorPtDiff = 0;
while ($row = $query->fetch_assoc()) {
$games[$row['gameID']]['gameID'] = $row['gameID'];
$games[$row['gameID']]['homeID'] = $row['homeID'];
$games[$row['gameID']]['visitorID'] = $row['visitorID'];
$games[$row['gameID']]['homeScore'] = $row['homeScore'];
$games[$row['gameID']]['visitorScore'] = $row['visitorScore'];
$games[$row['gameID']]['homeDiff'][$e] = $row['homeScore'] - $row['visitorScore'];
$games[$row['gameID']]['visitorDiff'][$e] = $row['visitorScore'] - $row['homeScore'];
$homePtDiff = $row['homeScore'] - $row['visitorScore'];
$visitorPtDiff = $row['visitorScore'] - $row['homeScore'];
if ((int)$row['homeScore'] != NULL && (int)$row['visitorScore'] != NULL) {
$scoreEntered = TRUE;
}else{
$scoreEntered = FALSE;
}
if ((int)$games[$row['gameID']]['homeScore'] > (int)$games[$row['gameID']]['visitorScore']) {
$games[$row['gameID']]['winnerID'] = $row['homeID'];
}else if ((int)$games[$row['gameID']]['homeScore'] < (int)$games[$row['gameID']]['visitorScore']){
$games[$row['gameID']]['winnerID'] = $row['visitorID'];
}
else{
$games[$row['gameID']]['winnerID'] = NULL;
}
$e++;
}
}
$sqlinner = "select * from " . DB_PREFIX . "pickmargin where weekNum = " . $wk . " and userID = " . $x . ";";
$queryinner = $mysqli->query($sqlinner);
if ($queryinner->num_rows > 0) {
$resultinner = $queryinner->fetch_assoc();
$currentPick = $resultinner['pickmargin'];
$currentGameID = $resultinner['gameID'];
$hidePicks = $resultinner['showPicks'];
$marginPts = 0;
$y_value = $x_value-1;
} else {
$currentPick = 'TBD';
}
if ($currentPick == $games[$row['gameID']]['homeID']){
$marginPts = (int)$games[$row['gameID']]['homeScore'] - (int)$games[$row['gameID']]['visitorScore'];
}
else{
$marginPts = (int)$games[$row['gameID']]['visitorScore'] - (int)$games[$row['gameID']]['homeScore'];
}
// ...
}
I need some help with this:
I'm doing a search with several parameters: Category, date(from), date(to)
Here's the code:
if (count($categorias) > 0) {
for ($i = 0; $i < count($categorias); $i++) {
if ($i == 0) {
$query = "WHERE id_subcategoria = " . $categorias[$i] . " ";
} else {
$query .= " OR id_subcategoria = " . $categorias[$i] . " ";
}
}
} else {
$query = "";
}
if (!$sql = $db->sql_query("SELECT * FROM actividades $query ORDER BY id DESC LIMIT " . $pageLimit . "," . PAGE_PER_NO)) {
message_die("DS", TRUE);
}
$total = $db->sql_numrows($sql);
if ($total != 0) {
while ($linha = $db->sql_fetchrow($sql)) {
$SqlEstado = $db->sql_query("SELECT * FROM tarifas WHERE id_actividade = " . $linha['id'] . " AND dia = '$data_min'");
First I get all the products that match the category and then I go to table "tarifas" to check if the product is available to be booked on that day.
So my question is: Can I do it all in one query? selecting the product and in case there's a rule in table "tarifas" fetch that rule.
If it's not clear enough please let me know so I can expose the problem in a different way, i'm really struggling with this.
Yes, you perform a JOIN on the id columns. If you want just those products that are in "tarifas" it will be an INNER JOIN, if you want the products even if they aren't in "tarifas" it will be "actividades LEFT JOIN tarifas ON ...".
Thanks for the help, user3038802!
Here's the code in case it helps anyone with the same problem:
if (!$sql = $db->sql_query("SELECT actividades.nome, actividades.id, actividades.dias, actividades.preco FROM actividades LEFT JOIN tarifas ON actividades.id = tarifas.id_actividade AND tarifas.dia = '$data_min' $query")) {
message_die("DS", TRUE);
}
I am setting a variable that contains an array as a constraint to a SELECT sql statement. However the constraint seems only to apply to one piece of data in the array. Why is this?
Code below:
<?php
include 'connection.php';
$Date = $_POST['date'];
$Unavail = 0;
$Avail = 0;
$Availid = 0;
$low = 99999;
$query = "SELECT username FROM daysoff WHERE date = '$Date'";
$dayresult = mysql_query($query);
while($request = mysql_fetch_array($dayresult)) {
$Unavail = $request;
echo "<span>" . $Unavail['username'] . " is unavailable.</br>";
}
$query1 = "SELECT Username, name, work_stats FROM freelance WHERE Username != '$Unavail[username]'";
$dayresult1 = mysql_query($query1);
while($request1 = mysql_fetch_array($dayresult1)) {
echo "<span>" . $request1['name'] . " is available.</br>";
if ($request1['work_stats']<=$low) {
$low = $request1['work_stats'];
$Availid = $request1['name'];
}}
echo "<span>" . $Availid . " is available on " . $_POST['date'] . " and is on workstat level " . $low . ".</span></br>";
?>
The output shows two names in the first echo but then shows one of those names as available in the second echo (these echos are only in place as part of my testing),
Many Thanks
The first query can have multiple results.
SELECT username FROM daysoff WHERE date = '$Date'
Let's say if gives two rows: Dave and John.
You're only keeping the last record so it will seem like Dave is available.
You should probably do something like:
$query = "SELECT username FROM daysoff WHERE date = '$Date'";
$dayresult = mysql_query($query);
$unavailable_users = array();
while($request = mysql_fetch_array($dayresult)) {
$unavailable_users[] = $request["username"];
echo "<span>" . $Unavail['username'] . " is unavailable.</br>";
}
$query1 = "SELECT Username, name, work_stats FROM freelance
WHERE NOT Username IN ('" . implode("','", $unavailable_users) . "')";
// etc
Or in one go with a LEFT JOIN:
SELECT `Username`, `name`, `work_stats`
FROM `freelance`
LEFT JOIN `daysoff` ON `freelance`.`Username` = `daysoff`.`username`
AND `daysoff`.`date` = '$Date'
WHERE
`daysoff`.`username` IS NULL
I keep getting the following error:
Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter
number: number of boundvariables does not match number of tokens
when trying to build a dynamic SQL query. Any idea where the damage is being done? I've searched for hours and still no luck
$park = $_POST["park"];
$lecturestyle_id = $_POST["lecturestyle"];
$group_size = $_POST["groupsize"];
$roomstructure_id = $_POST["roomstructure"];
$array = explode(",", $_POST["facilities"]);
// change Mon here
echo '<td class="gridSide">
Mon
';
// build facilities search
for($i = 0; $i < count($array); $i++){
if ($array[$i]!=0) {
$fac .= ' AND facilities_id='.$array[$i].'';
}
else
$fac .= '';
}
echo '</td>';
for ($i = 1; $i <= 9; $i++)
{
// change mon here
echo '<td class="box" id="mon'.$i.'">';
// dynamically build sql query
$sql =
"
SELECT DISTINCT COUNT(*) FROM ts_room rm
LEFT JOIN ts_roomfacilities rf
ON rm.id = rf.room_id
LEFT join ts_facilities f
ON f.id = rf.facilities_id
LEFT JOIN ts_building b
ON rm.building_id=b.id
WHERE capacity>=:group_size";
$sql .= $fac;
if($park!="Any") {
$sql .= " AND b.park_id=:park";
}
if($lecturestyle_id!="Any") {
$sql .= " AND lecturestyle_id=:lecturestyle_id";
}
if($roomstructure_id!="Any") {
$sql .= " AND roomstructure_id=:roomstructure_id";
}
$sql .= " AND rm.id NOT IN
(SELECT COUNT(*)
FROM ts_request rq
LEFT JOIN ts_allocation a ON a.request_id = rq.id
WHERE
day_id=1 AND period_id=:period
OR a.status IS NOT NULL
AND a.status IN ('Pending','Declined','Failed'))";
$stm = $pdo->prepare( $sql );
$stm->execute( array( ':roomstructure_id' => $roomstructure_id, ':lecturestyle_id' => $lecturestyle_id,
':group_size' => $group_size, ':park' => $park, ':period' => $i));
$rows = $stm->fetchColumn();
echo $rows.'<br>free</td>';
echo '</td>';
}
When you perform $stm->exectue, you're providing tokens for ':roomstructure_id', ':lecturestyle_id', ':group_size', ':park' and ':period', regardless of whether they actually exist in the query, i.e. if any of them are equal to 'Any'.
What you should do is build your value array as you're building your query... adding values to it whenever a field's search value is not 'Any'.
eg
if($park!="Any") {
$sql .= " AND b.park_id=:park";
$searchArray[':park'] = $park;
}
Your not assigning :group_size parameter, and $stm->execute() accepts a single dimensional array.
Try this:
<?php
require_once("../resources/php/connection.php");
$park = $_POST["park"];
$lecturestyle_id = $_POST["lecturestyle"];
$group_size = $_POST["groupsize"];
$roomstructure_id = $_POST["roomstructure"];
$array = explode(",", $_POST["facilities"]);
// change Mon here
echo '<td class="gridSide">Mon';
// build facilities search
echo '</td>';
$fac = null;
for($i = 0; $i < count($array); $i++){
if ($array[$i]!=0) {
$fac .= ' AND facilities_id='.$array[$i].'';
}
}
for ($i = 1; $i <= 9; $i++){
// change mon here
echo '<td class="box" id="mon'.$i.'">';
// dynamically build sql query
$sql ="SELECT DISTINCT COUNT(*) FROM ts_room rm
LEFT JOIN ts_roomfacilities rf
ON rm.id = rf.room_id
LEFT join ts_facilities f
ON f.id = rf.facilities_id
LEFT JOIN ts_building b
ON rm.building_id=b.id
WHERE capacity >= :group_size";
$sql .= $fac;
if($park!="Any") {
$sql .= " AND b.park_id=:park";
$searchArray[':park'] = $park;
}
if($lecturestyle_id!="Any") {
$sql .= " AND lecturestyle_id=:lecturestyle_id";
$searchArray[':lecturestyle_id'] = $lecturestyle_id;
}
if($roomstructure_id!="Any") {
$sql .= " AND roomstructure_id=:roomstructure_id";
$searchArray[':roomstructure_id'] = $roomstructure_id;
}
$sql .= " AND rm.id NOT IN
(SELECT COUNT(*)
FROM ts_request rq
LEFT JOIN ts_allocation a ON a.request_id = rq.id
WHERE
day_id=1 AND period_id=:period
OR a.status IS NOT NULL
AND a.status IN ('Pending','Declined','Failed'))";
//Dont forget these
$searchArray[':period'] = $i;
$searchArray[':group_size'] = $group_size;
$stm = $pdo->prepare($sql);
$stm->execute($searchArray);
$rows = $stm->fetchColumn();
echo $rows.'<br>free</td>';
echo '</td>';
}
?>