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.
Related
I have 2 tables - users and articles.
users:
user_id (int)
name (varchar)
articles:
article_id (int)
user_id (int)
title (varchar)
description (text)
In my application I need to display 20 RANDOM articles on a page.
My query is like this:
SELECT a.title
, a.description
, u.name
FROM articles a
JOIN users u
USING (user_id)
ORDER
BY RAND()
LIMIT 20
A user can have any number of articles in the database.
Now the problem is sometimes out of 20 results, there are like 9-10 articles from one single user.
I want those 20 records on the page to not contain more than 3 (or say 4) articles from a particular user.
Can I achieve this through SQL query. I am using PHP and MySQL.
Thanks for your help.
You could try this?
SELECT * FROM
(
SELECT B.* FROM
(
SELECT A.*, ROW_NUMBER() OVER (PARTITION BY A.USER_ID ORDER BY A.R) USER_ROW_NUMBER
FROM
(
SELECT a.title, a.description, u.name, RND() r FROM articles a
INNER JOIN users u USING (user_id)
) A
) B
WHERE B.USER_ROW_NUMBER<=4
) C
ORDER BY RAND() LIMIT 20
Mmm, intresting I don't think this is possible through a pure sql query.
My best idea would be to have an array of the articles that you'll eventually display query the database and use the standard SELECT * FROM Articles ORDER BY RAND() LIMIT 20
The go through them, making sure that you have indeed got 20 articles and no one has breached the rules of 3/4 per user.
Have another array of users to exclude, perhaps using their user id as an index and value of a count.
As you go through add them to your final array, if you find any user that hits you rule add them to the array.
Keep running the random query, excluding users and articles until you hit your desired amount.
Let me try some code (it's been a while since I did php)
$finalArray = [];
$userArray = [];
while(count($finalArray) < 20) {
$query = "SELECT * FROM Articles ";
if(count($finalArray) > 0) {
$query = $query . " WHERE articleID NOT IN(".$finalArray.")";
$query = $query . " AND userID NOT IN (".$userArray.filter(>4).")";
}
$query = $query . " ORDER BY Rand()";
$result = mysql_query($query);
foreach($row = mysql_fetch_array($result)) {
if(in_array($finalArray,$row) == false) {
$finalArray[] = $row;
}
if(in_array($userArray,$row[userId]) == false) {
$userArray[$row[userId]] = 1;
}
else {
$userArray[$row[userId]] = $userArray[$row[userId]] + 1;
}
}
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;--).
I am writing a Custom Query in WordPress database to get the previous record from the posts table.
Example:
I have an ID of 34975; after I query the database I should get the ID as 34972, which is the previous record ID.
SQL
$results = $wpdb->get_results( "SELECT * FROM agencies_posts WHERE ID = '34975 ' LIMIT 1", OBJECT );
foreach( $results as $item ){
$previous_depature_port = $item->ID;
}
If I'm understanding your question correctly, you need to add ORDER BY and use < instead of =:
SELECT *
FROM agencies_posts
WHERE ID < 34975
ORDER BY ID DESC
LIMIT 1
Pretty sure you want:
select *
from agencies_posts
where id = (select max(id) from agencies_posts where id < '34975')
If the 'current' id is what's known and you just want the one prior.
Select everything with an id less than the one you are interested in, and only grab the first one
SELECT *
FROM agencies_posts
WHERE ID < '34975 '
ORDER BY ID DESC LIMIT 1"
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 two tables for the users; a login table and the user profile table.
I want to compare a value from 'userprofiletable' to another value from another table called posts. If the value is equal, it shows a list.
I have the following code. The problem is that it is not comparing the value in the posts table with the value of the session from user profile table.
Could someone help me please?
<?php
$limit = '5';
$dbreq = 'SELECT * FROM `posts` ORDER BY `pos` DESC';
$dbdata = mysql_query($dbreq);
while($dbval = mysql_fetch_array($dbdata))
{
if (($dbval['city'] == $_SESSION['student_city'])) { //checks for last 4 accomodation
if ($limit >= '1') {
echo '<tr><td>'.$dbval['title'].'</td></tr>';
$limit = $limit -'1';
}
}
}
?>
I also want to get the value of userprofiletable and post it in the posts table. For example, when somebody make a new post.
Your post is a bit unclear, but I think this is what you want:
<?php
$userid = 11542;//Sample uid. You will have to figure this out and set it.
$limit = 5;
$dbreq = "SELECT * FROM `posts` WHERE `userid`=".$userid." ORDER BY `pos` DESC LIMIT=".$limit.";";
$dbdata = mysql_query($dbreq);
while($dbval = mysql_fetch_array($dbdata))
{
if (($dbval['city'] == $_SESSION['student_city'])) { //checks for last 4 accomodation
echo '<tr><td>'.$dbval['title'].'</td></tr>';
}
}
?>
The question is not clear, but there could be two answers:
To reproduce your code, you can do in ONE sql query:
$dbreq = 'SELECT *
FROM `posts`
WHERE city="'.mysql_real_escape_string($_SESSION['student_city']).'"
ORDER BY `pos` DESC
LIMIT 4';
If, however, there are two tables, then you need "LEFT JOIN" linking the posts table to the userprofile table
$dbreq = 'SELECT p.*, u.*
FROM posts p
LEFT JOIN userprofiletable up ON p.UserID=up.UserID
WHERE up.city="'.mysql_real_escape_string($_SESSION['student_city']).'"
ORDER BY p.pos DESC
LIMIT 4';
(UserID in the table above is the name of the field in the posts table and userprofiletable that links the two.)