I am trying to refer the parent query fetched array in sub query of same statement. I have a news table and I want to get a specific news by its title and 10 more news which have id lower than that specific news. I want in one statement of Sql and i am php to fetch array.
<?php
// $_GET['q'] is title
include('db.php');
$result = array();
$sel = "SELECT * FROM news WHERE title = '".$_GET['q']."' "; // AND 10 MORE NEWS WHICH HAVE ID LOWER THAN THIS $_GET['q'] ID .
$qry = #mysqli_query($conn , $sel);
$num = mysqli_num_rows($qry);
while($row = #mysqli_fetch_array($qry)) {
array_push($result, array('id' => $row['id'] , 'title' => $row['title'] , 'desc' => $row['about'] , 'image' => $row['image'] , 'time' => $time , 'htitle' => $row['Htitle'] , 'habout' => $row['Habout']));
}
echo json_encode(array('result' => $result));
?>
Your original query is
SELECT * FROM news WHERE title = :title.
If you really want to use a subquery use something along the lines of
SELECT
*
FROM news
WHERE id <
(SELECT
id
FROM news
WHERE title = :title
LIMIT 1)
ORDER BY id DESC
LIMIT 10
A final note: PLEASE use parameters in your query, because you are WIDE OPEN to SQL injection (think about when $_GET['q'] has a value of ; DROP TABLE news;--).
Related
So i have 2 queries, I am trying to run one inside of a loop (unsuccessfully), but I'm thinking there might be a possibility that I can combine the 2 of them.
Table profile_posts
ID
post_title
post_body
user_id
post_date
Table profile_posts_likes
ID
likes
user_like_id
post_id
$baseURL = 'Data.php'; //Grab page for pagination
$id = $_GET['id']; //Grab id from link
$limit = 10; //Limit returns to 10
//Select statement that grabs results from profile_posts table
$postQuery = "SELECT * FROM profile_posts WHERE user_id = :id ORDER BY post_date DESC LIMIT $limit"; //First Query
// Count of all records
$rowCount = countRecords($conn, $id);
// Initialize pagination class
$paginationConfig = array(
'postID' => $id,
'baseURL' => $baseURL,
'totalRows' => $rowCount,
'perPage' => $limit,
'contentDiv' => 'postContent',
'link_func' => 'searchFilterProfile'
);
$pagination = new Pagination($paginationConfig);
$profilePost = $conn->prepare($postQuery);
$profilePost->bindParam(":id", $id);
$profilePost->execute();
if($profilePost->rowCount() > 0){
foreach($postDisplay as $row){
$likeQuery = "SELECT id, COUNT(likes) as likeCount, user_Like_id, post_id FROM profile_posts_likes WHERE post_id = :postID"; //Second Query
$likeQuery = $conn->prepare($likeQuery);
$likeQuery->bindParam(":postID", $row['id']); //Grab id from first query
$likeQuery->execute();
$postlikeQuery = $likeQuery->fetchAll();
if($likeQuery->rowCount() > 0){
//Display like buttons, when user clicks "Like" button, send data through Ajax
//and update page with "Liked"
}
}
}
What this does is displays the posts on the users profile page, and then when a user views their page, they can 'Like' the post or 'unlike it'...Using Ajax to update page
Now is there a way that I can combine those 2 queries together instead of running one inside of the loop. I tried tossing a WHERE EXISTS in there to combine the Select statements, but no luck.
Appreciate any help. Thanks in advance.
You may express your query using a join:
SELECT ppl.id, ppl.user_Like_id, ppl.post_id
FROM profile_posts_likes ppl
INNER JOIN
(
SELECT *
FROM profile_posts
WHERE user_id = :id
ORDER BY post_date DESC
LIMIT $limit
) pp
ON pp.id = ppl.post_id;
Selecting COUNT in the second query makes no sense, as you are not using GROUP BY.
I am creating a CRM for myself. My database contains four tables. In a section of my site I want to while loop all [note] and [task] that are connected to a [contact].
[link] (Linking contact to task)
'id' 'contact_id' 'task_id'
'1' '1' '1'
[contact]
'id' 'contact_name'
'1' 'Robert'
[task]
'id' 'description' 'due_date'
'1' 'Call to say hello' '2016:06:13'
[note] (Note link directly to the contact)
'id' 'contact_id' 'text' 'date_entered'
'1' '1' 'I met Robert on the weekend.' '2016:06:12'
The only way I know at the moment is creating two seperate queries. One to select and display the task information...
$contact_id_for_example = '1'
$find_the_link = $mysqli->query("SELECT * FROM link WHERE contact_id = '$contact_id_for_example'");
if($find_the_link->num_rows != 0){
while($link_rows = $find_the_link->fetch_assoc())
{
$link_task_id = $link_rows['task_id'];
$find_the_task = $mysqli->query("SELECT * FROM task WHERE id = '$link_task_id' ORDER BY due_date");
if($find_the_task->num_rows != 0){
while($task_rows = $find_the_task->fetch_assoc())
{
$task_description = $task_rows['description'];
echo '<li>'.$task_description.'</li>';
}
}
..and one to display the note information..
$note_select = $mysqli->query("SELECT * FROM note WHERE contact_id = '$contact_id_for_example' ORDER BY 'date_entered'");
if($note_select->num_rows != 0){
while($note_rows = $note_select->fetch_assoc())
{
$note_text = $note_rows['text'];
echo '<li>'.$note_text.'</li>';
}
}
The problem with my method is that the above code would print all of the matching tasks first then all of the notes below that. Even if the first note was entered/due well before the task they will always print after the tasks.
I have looked into JOINS and don't see how that would work in this instance due the [link] table interconnecting the [contact] and [task] table.
I have also searched around this site and others and noticed Multiple Queries. but from what I have read so far this doesn't solve the issue either.
Here is my attempt:
$test_contact_id = '1068';
$query = "SELECT * FROM link WHERE contact_id = '$test_contact_id';";
$storing_link = $query->num_rows;
$find_task_id = $storing_link->fetch_fields();
$find_task_id->task_id;
$query .= "SELECT * FROM task WHERE id = '$find_task_id';";
$storing_task = $query->num_rows;
$find_task_description = $storing_task->fetch_fields();
$task_description->text;
$query .= "SELECT * FROM note WHERE contact_id = '$test_contact_id';";
$storing_note = $query->num_rows;
$find_note_text = $storing_note->fetch_fields();
$note_text = $find_note_text->text;
if($mysqli->multi_query($query)){
echo '<p>'.$task_description.' :: '.$note_text.'</p>';
}
JOINs are EXACTLY what you want. You just need a bit of logic to detect when you're moving between record sets. e.g. a simple state machine:
SELECT ...
ORDER BY table1.foo, table2.bar, table3.baz
$prev1 = $prev2 = $prev3 = null;
while($row = fetch()) {
if ($row['table1.foo'] != $prev1) {
start a new table1 output
$prev1 = $row['table1.foo'];
}
... repeat for tables 2&3,
... output "core" data
}
I'm trying to fetch the last 100 row but only one row is being displayed as a result
here is my php code:
<?php
require_once("variables.php");
$db = new ezSQL_mysql($GLOBALS['database_username'],$GLOBALS['database_password'],$GLOBALS['database_database'],$GLOBALS['database_server']);
header('Content-Type: application/json');
echo "{\"office\":\"0\",\"dept\":{\"desk\":[";
$symbols = addslashes($_GET['symbols']);
$symbolsArr = explode(",", $symbols);
foreach($symbolsArr as $s) {
$last = $db->get_row("select * from data where name='$s' order by id desc limit 0,100");
$jsonArray = array('name' => $s,
'phone' => $last->phone,
'active' => $last->active);
echo json_encode($jsonArray);}
echo "]}}";
?>
UPDATE> based on recommendations below I have changed get_row to get_results but the code broken now and it's not displaying any error.
Read the documentation on the database class you are using (ezSQL):
----------------------------------------------------
Example 2
----------------------------------------------------
// Get one row from the database..
$user = $db->get_row("SELECT name,email FROM users WHERE id = 2");
echo $user->name;
echo $user->email;
You are issuing a statement that is specifically to fetch one single row.
What you want to use is get_results() method instead of get_row() method.
I re-read your question and see that you were doing limit 0,100 which returns 100 rows starting with 0 (first). i thought you were trying to cycle those rows but I can see you are actually trying to only get the last row... my bad, derp.. well here - you are reversed somewhat in your query - should be 100,1 as you want the 100th row and only 1 row.
$last = $db->get_row("select * from data where name='{$s}' order by id desc limit 100,1");
$jsonArray = array('name' => $s,
'phone' => $last->phone,
'active' => $last->active);
Since you are trying to get last 100 rows use following statement:
$last = $db->get_results("select * from data where name='$s' order by id desc limit 100");
instead of
$last = $db->get_row("select * from data where name='$s' order by id desc limit 0,100");
ezSql get_results is the method which you need to use for retrieving multiple results from database.
I am trying to make a page with a list of posts, and underneath each post all the comments belonging to that post. Initially I wanted to use just one query to retrieve all the posts + comments using the SQL's JOIN, but I find it impossible to for example retrieve a post with multiple comments. It only displays the posts with a maximum of 1 comment per post, or it just show a post multiple times depending on the amount of comments.
In this related question, somebody talked about using 2 queries:
How to print posts and comments with only one sql query
But how do I do this?
I've got the query and a while loop for posts, but I obviously don't want to run a query for comments for each post inside that loop.
$getPost = mysql_query('SELECT p.post_id,
p.user_id,
p.username,
p.content
FROM post p
ORDER BY p.post_id DESC');
while($row = mysql_fetch_array($getPost))
{
...
}
Table structure (reply is the table for storing comments):
POST (post_id (primary key), user_id, username, content, timestamp)
REPLY (reply_id (primary key), post_id, username, reply_content, timestamp)
You can do it in a single query, which is OK if the amount of data in your original posts is small:
$getPost = mysql_query('SELECT
p.*,
r.reply_id, r.username r_username, r.reply_content, r.timestamp r_timestamp
FROM post p
left join reply r
ORDER BY p.post_id DESC'
);
$posts = array();
$last_id = 0;
while($row = mysql_fetch_array($getPost))
{
if ($last_id != $row['post_id']) {
$posts[] = array(
'post_id' => $row['post_id'],
'user_id' => $row['user_id'],
'username' => $row['username'],
'content' => $row['content'],
'timestamp' => $row['timestamp'],
'comments' => array()
);
}
$posts[sizeof($posts) - 1]['comments'][] = array(
'reply_id' => $row['reply_id'],
'username' => $row['r_username'],
'reply_content' => $row['reply_content'],
'timestamp' = $row['r_timestamp']
);
}
Otherwise, break it into two queries like so:
$getPost = mysql_query('SELECT
p.*,
FROM post p
ORDER BY p.post_id DESC'
);
$rows = array();
$ids = array();
$index = array();
while($row = mysql_fetch_assoc($getPost)) {
$row['comments'] = array();
$rows[] = $row;
$ids[] = $row['post_id'];
$index[$row['post_id']] = sizeof($rows) - 1;
}
$getComments = mysql_query('select r.* from replies r where r.post_id in ("'
. join('","', $ids)
. '")');
while ($row = mysq_fetch_assoc($getComments)) {
$rows[$index[$row['post_id']]]['comments'][] = $row;
}
... Or something like that. Either option allows you to litter your first query with WHERE clauses and so forth to your heart's content. The advantage of the 2nd approach is that you don't re-transmit your original post data for each comment!
In order to also get those posts without comments, you need to use a LEFT OUTER JOIN. In that case, any row in the first table without any corresponding rows in the second table will be paired with a row consisting of null values.
SELECT * FROM posts
LEFT OUTER JOIN comments ON posts~post_id = comments~post_id;
By the way: there is also a RIGHT OUTER JOIN. When you would use that, you would get all comments, including those where the parent post got lost somehow, but no posts without comments.
I have a table containing 4 articles with id 1,2,3 and 4 as well as ordering value 1,2,3,4.
They have separate columns for their title, image etc. I need to get them distinctly with where clause. So i did:
For article 1:
//topstory1
$sql_topstory1 ="SELECT * FROM topstory WHERE story_active='1' && story_order='1'";
$result_topstory1 = mysql_query($sql_topstory1);
$row_topstory1 = mysql_fetch_array($result_topstory1);
$story1_title = $row_topstory1['story_title'];
$story1_abstract = $row_topstory1['story_text'];
And for article 2
//topstory2
$sql_topstory2 ="SELECT * FROM topstory WHERE story_active='1' && story_order='2'";
$result_topstory2 = mysql_query($sql_topstory2);
$row_topstory2 = mysql_fetch_array($result_topstory2);
$story2_title = $row_topstory2['story_title'];
$story2_abstract = $row_topstory2['story_text'];
As I have to reuse them in a page.
PROBLEM IS, the first query works but the second one doesn't. It seems like MySql cannot execute two consecutive queries on the same table in a single php file. But I think there is a simple solution to this...
Please help me soon :( Love you guys :)
There are several possible reasons for the second query to fail, but the fact that it's the second query in the file does not cause it to fail.
I would expect that article 2 does not have the active flag set to 1, causing you to get an empty result set.
Another option is that you may have closed the mysql connection after the first query, then you can't execute another query. (General rule: don't close database connections. PHP takes care of that.)
Why not just get them both with 1 query?
$sql_topstory ="SELECT * FROM topstory WHERE story_active='1' && story_order IN(1, 2) ORDER BY story_order DESC";
$result_topstory = mysql_query($sql_topstory) or trigger_error('Query Failed: ' . mysql_error());
while ($row = mysql_fetch_assoc($result_topstory)) {
$title[] = $row['story_title'];
$abstract[] = $row['story_abstract'];
}
// Then to display
echo 'Story 1 is ' . $title[0] . ' with an abstract of ' . $abstract[1];
There are plenty of ways to do this, this is just a simple demonstration.
$query = <<<SQL
SELECT
story_title
, story_text
FROM
topstory
WHERE
story_active
ORDER BY
story_order ASC
SQL;
$result = mysql_query($query);
$stories = array();
while ($row = mysql_fetch_assoc($result)) {
$stories[] = $row;
}
Now you have an array of stories like so:
array(
0 => array(
'story_title' => ?
, 'story_text' => ?
)
, 1 => array(
'story_title' => ?
, 'story_text' => ?
)
)
Should be pretty easy to iterate through.