Join two queries in mysql/php - php

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);
}

Related

Joining two tables based off a condition SQL

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.

How to fetch from 3 tables?

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

Pull specific values from array to calculate

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'];
}
// ...
}

Can you use php with an SQL case?

I am trying to optimize some of my code and i believe i need an if/else or case to do this, however I think i would need php in the query to get it to work
here is the code I am trying to optimize
$sql = "SELECT value, COUNT(*) AS count
FROM sodsurvey LEFT OUTER JOIN age
ON sodsurvey.age_id = age.id
WHERE value IS NOT NULL AND office_id = " . $office_id . "
GROUP BY age_id; ";
if ($_SESSION['filteryear'] != 0 && $_SESSION['filtermonth'] != 0) {
$sql = "SELECT value, COUNT(*) AS count
FROM sodsurvey LEFT OUTER JOIN age
ON sodsurvey.age_id = age.id
WHERE value IS NOT NULL AND office_id = " . $office_id . "
AND year = " . $_SESSION['filteryear'] . " AND month = " . $_SESSION['filtermonth'] . "
GROUP BY age_id; ";
} else if ($_SESSION['filteryear'] != 0 || $_SESSION['filtermonth'] != 0) {
$sql = "SELECT value, COUNT(*) AS count
FROM sodsurvey LEFT OUTER JOIN age
ON sodsurvey.age_id = age.id
WHERE value IS NOT NULL AND office_id = " . $office_id . "
AND (year = " . $_SESSION['filteryear'] . " OR month = " . $_SESSION['filtermonth'] . ")
GROUP BY age_id; ";
}
and this is what I have tried to give you a rough idea of what I am trying to achieve
$filter = "";
if ($_SESSION['filteryear'] != 0 && $_SESSION['filtermonth'] != 0) {
$filter = "AND year = " . $_SESSION['filteryear'] . " AND month = " . $_SESSION['filtermonth'] . ""
} else if ($_SESSION['filteryear'] != 0 || $_SESSION['filtermonth'] != 0) {
$filter = "AND (year = " . $_SESSION['filteryear'] . " OR month = " . $_SESSION['filtermonth'] . ")"
}
$sql = "SELECT value, COUNT(*) AS count
FROM sodsurvey LEFT OUTER JOIN age
ON sodsurvey.age_id = age.id
WHERE value IS NOT NULL AND office_id = " . $office_id . "
CASE
WHEN ".isset($filter)." THEN ". $filter ."
END
GROUP BY age_id; ";
You can build up an array of filters depending on which values (year, month, etc) are set, and then combine them all into the WHERE clause. You don't need to worry about all the separate cases where both are set, or one are set, and so on.
I would also strongly echo the advice above that recommended looking into prepared statements, but this will hopefully get you on your way.
<?php
$office_id = 10;
$_SESSION['filteryear'] = 2016;
$_SESSION['filtermonth'] = 12;
$filters = [
"value IS NOT NULL",
"office_id = {$office_id}",
];
if ($_SESSION['filteryear']) {
$filters[] = "year = {$_SESSION['filteryear']}";
}
if ($_SESSION['filtermonth']) {
$filters[] = "month = {$_SESSION['filtermonth']}";
}
$sql = "
SELECT value, COUNT(*) AS count
FROM sodsurvey
LEFT JOIN age ON sodsurvey.age_id = age.id
WHERE " . implode(' AND ', $filters) . "
GROUP BY age_id;
";
The implode line combines each filter that's been set into a single WHERE clause.
is it valid to use PHP with a case in my attempt above?
No. PHP code cannot be part of your SQL query, however your PHP code can generate SQL query
In MySQL, I am trying to find a way to optimize my code
Just make your SQL code generated by PHP code based on all the conditions. You can easily concatenate strings being partions of your query conditionally.

PHP & Mysql Not ordered correctly

I have latest MySQL version (5.5) and this is the screenshot of groupid field
I didn't touch anything yet, but some cells are not ordered correctly like this
But if I click groupid name in the top, it will ordered correctly like this:
Below PHP code output is like first screenshot above, that are not ordered correctly. Please help how to make the output ordered correctly, like it is displayed in the second screenshot above,
Maybe add code like this : order by id asc, but which is the right place to add it below?
$group_ids = explode(" ", $options['groupchoice_ids']);
$groupsql = "SELECT id, title FROM " . TABLE_PREFIX . "thegroup WHERE";
$first = true;
foreach($group_ids as $value)
{
if (!$first)
{
$groupsql = $groupsql . " OR ";
}
else
{
$first = false;
}
$groupsql = $groupsql . " id = '" . $value . "' ";
}
$kh_optionsgroup = '<select name = "accounttype">';
$checksec = $db->query_read($groupsql);
if ($db->num_rows($checksec))
{
while ($lboard = $db->fetch_array($checksec))
{
$kh_optionsgroup = $kh_optionsgroup . "<option value
='" . $lboard['id'] . "'>" . $lboard['title'] . "</option>";
}
}
$verifystring = '$human_verify';
$kh_optionsgroup = $kh_optionsgroup . "</select>";
At the end of your query, you need to set an order, like so:
$groupsql="SELECT id, title FROM " . TABLE_PREFIX . "thegroup WHERE";
$first=true;
foreach($group_ids as $value){
if(!$first){
$groupsql = $groupsql." OR ";
}else{
$first = false;
}
$groupsql = $groupsql." id = '".$value."' ORDER BY groupid ASC";
}
ORDER BY id ASC
This will make the query return its results in ascending order from the groupid column. Simply change ASC to DESC if you want it to go descendinng (high->low).

Categories