I'm creating a image gallery where people can add comments to each uploaded image.
I've made a db tabel for all comments including a foreign key to match the image table.
My SQL variable looks like this and seems to work fine:
$all_comments_one_image_sql="
SELECT userimage.id, image_id, comment, id, comment_date
FROM userimage, image_comment
WHERE image_comment.image_id=userimage.id
ORDER BY comment_id DESC
";
But when I'm doing my while function for all my gallery images, where and how would I echo the right comments to each image?
You should be doing a left join like this:
select userimage.id,
com.image_id,
com.comment,
com.id,
com.comment_date
FROM userimage
LEFT JOIN image_comment as com ON com.image_id=userimage.id
WHERE userimage.id = ?
ORDER BY com.id DESC
First of all create a function for getting image comments:
function getImageComments($imageId){
$query = "SELECT userimage.id, image_id, comment, id, comment_date
FROM userimage
LEFT JOIN image_comment
ON image_comment.image_id=userimage.id
WHERE image_id = $imageId
ORDER BY comment_id DESC
";
mysql_query($query);
return mysql_fetch....
}
I also redo your query for better performance.
So whnever you are loading an image, call the function with the proper image id and get its comments.
You have to check for the right image_id
$all_comments_one_image_sql = "
SELECT userimage.id, image_id, comment, id, comment_date
FROM userimage, image_comment
WHERE image_comment.image_id=userimage.id AND image_id = ?
ORDER BY comment_id DESC
";
where ? is the id of the image you want to Show comments - if you use pdo, you can just bind the image id and don't have to care about escaping.
If you have a summary page for all images, you can add the results in an assoc array, where the key is your image id
$comments[] = array();
while ($row = $res->fetch()) {
if (empty($comments[$row->image_id])) {
$comments[$row->image_id] = array();
}
$comments[$row->image_id][] = $row;
}
To show the comments, you can just look, if $comments[$image_id] is an array and show the conent
Related
The user_id can be found on the replies table but also in the profiles table. The profiles table has the real_name column.
Below I get all the replies for a specific article_id. My question is how do I echo the real_name of the commenters that is saved into the profiles table ?
I am consider the performance of this.
$replies = mysql_query("select * from replies where article_id = '$row[id]' order by timestamp desc");
while($reply = mysql_fetch_assoc($replies)) {
I can echo the comments from the replies table, but how do I echo the real_name of each?
}
Try That :
$replies = mysql_query("select * from replies,profiles where article_id = '$row[id]' AND replies.user_id=profiles.id order by timestamp desc");
Good luck !
I've searched and found ways to do queries inside queries, but I have not found the right answer.
What I am trying to do is to fetch comments from the table called users_profiles_comments and by doing that I will get the field of '.$member["author"].'. Then I want to show who made the comment with their rank and a display picture.
But because there is no user details stored in the comments table because its for comments, I need to create a query inside of my query result where I can have this:
"SELECT * FROM users WHERE username = $member['author'] ORDER BY `id` ASC"
The '.$member["author"].' value comes from the main query but I need it so it can find fields in my users table.
$sql = "SELECT * FROM users_profiles_comments WHERE postid = '1' ORDER BY `id` ASC";
$stm = $dbh->prepare($sql);
$stm->execute();
$users = $stm->fetchAll();
foreach ($users as $row) {
print '
<img src="'.$member["profilepic"].'" style="float:left;margin-right:10px;" width="80px" height="85pxm">
<h4>'. $row["author"] .'
<small>'. $row["date"] .'</small>
</h4>
<p>'. $row["content"] .'</p><hr> </a></li>';
}
echo '
</div>
';
I hope you understand.
Edit:
The database.
users Table
http://img855.imageshack.us/img855/4387/qyjl.png
users_profiles_comments table
http://i.imgur.com/aKRF5MN.png
But because there is no user details stored in the comments table because its for comments
This is good. You do not want to have your database information duplicated in both tables (de-normalized data) - there is no need.
Generally a foreign key is added to inverse side of the relationship. This would mean you have a user_id column within your comments table, allowing you to select the data in one query using a JOIN
SELECT comment.*, user.name AS comment_author
FROM comment
INNER JOIN user ON user.id = comment.user_id
WHERE user.id = 123
Edit - I flipped to JOIN to return comments rather than users, (as you said "to fetch comments") however both ways will work, it just depends which side of the relationship you are on.
Edit 2 To respond to your comment;
How would I be able to show this on my PHP code on the result?
you can be more specific with the above query (not use *) and render it as follows :
$sql = "
SELECT
comment.`date` as comment_date,
comment.content,
user.name AS author_name,
user.profilepic as author_pic
FROM
users_profiles_comments as comment
INNER JOIN
user ON user.id = comment.user_id
WHERE
comment.postid = 1
";
//...
$comments = $stmt->fetchAll();
foreach ($comments as $comment) {
echo '<img src="' . $comment['author_pic'] . '"/>';
echo '<h4>' . $comment['author_name'] . '<small>' . $comment['comment_date'] .'</small></h4>';
echo '<p>' . $comment['content'] . '</p>';
}
You can select member name in SQL statement. You can try this query, this query will bring all the information from two table if users.username = users_profiles_comments.author
WAY 1:
SELECT t1.*, t2.* FROM
(
SELECT * FROM users WHERE username = '.$member["author"].' ORDER BY `id` ASC
) AS t1
LEFT JOIN
(
SELECT * FROM users_profiles_comments WHERE postid = '1' ORDER BY `id` ASC
) AS t2
ON t1.username = t2.author
Finally, do your foreach to print
===================================================================
WAY 2:
You can try this also-
SELECT *,
(SELECT profilepic FROM users WHERE users.username = users_profiles_comments.author) AS profilepic
FROM users_profiles_comments WHERE postid = '1' ORDER BY `id` ASC
And print profilepic using $row['profilepic'] in your foreach loop
=====================================================================
WAY 3:
SELECT t1.*, t2.* FROM
(
SELECT * FROM comments WHERE postid = '1'
) AS t1
LEFT JOIN
(
SELECT * FROM users
) AS t2
ON t1.author = t2.username
What I understand is that you need to get information about the user from another table called user_profile_comments, based on the user id (correct me if wrong: :-)). Use a left outer JOIN to fetch data from another table, limited on user id.
See http://www.w3schools.com/sql/sql_join.asp for more info.
i have a online application for wich i require a sort of dashboard (to use the white-space).
There are three tables used for the operation:
1.) categories: id, name
2.) entries: id, name, description, category_id, created, modified
3.) entryimages: id, filename, description, entry_id
on the dashboard i want to show 4-5 entries (with thumbnail images, so i require joins to the entryimages table and the categories table) for each category.
I read through some articles (and threads on s.o.) like this one:
http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
But am still not getting it right, i've tried to first extract all categories and for each and every category build a query and with "all union" attach them to one, but that is not working.
The last version of code i used:
foreach($categories as $id => $name)
{
$query .= "SELECT `entry`.`id`,
`entry`.`name`,
`entry`.`description`,
`entry`.`category_id`,
`entry`.`created`,
`entry`.`modified`,
`entryimages`.`filename`,
`entryimages`.`description`
FROM `entries` as `entry` LEFT JOIN `entryimages` ON `entryimages`.`entry_id` = `entry`.`id`
WHERE `entry`.`category_id` = $id ";
if($i < count($groups))
{
$query .= 'UNION ALL ';
}
$i++;
}
$result = mysql_query($query);
Does anybody know what is the best right to accomplish this operation?
Thanks 1000
On the dashboard if you want to show three entries, the way you are doing is wrong. If my understanding is right, the entire query will be something like
"SELECT `entry`.`id`,
`entry`.`name`,
`entry`.`description`,
`entry`.`category_id`,
`entry`.`created`,
`entry`.`modified`,
`entryimages`.`filename`,
`entryimages`.`description`
FROM `entries` as `entry`
INNER JOIN categories
ON (entry.category_id = categories.id)
LEFT JOIN (SELECT * FROM `entryimages` WHERE `entry_id` = `entry`.`id` LIMIT 1) AS `entryimages`
ON `entryimages`.`entry_id` =`entry`.`id`
ORDER BY `entry`.`created` DESC LIMIT 5";
Your code looks ok to me you should just add a LIMIT clause so that you get just five of them and an ORDER BY clause to get the latest
$query .= "SELECT `entry`.`id`,
`entry`.`name`,
`entry`.`description`,
`entry`.`category_id`,
`entry`.`created`,
`entry`.`modified`,
`entryimages`.`filename`,
`entryimages`.`description`
FROM `entries` as `entry` LEFT JOIN `entryimages` ON `entryimages`.`entry_id` = `entry`.`id`
WHERE `entry`.`category_id` = $id ORDER BY `entry`.`created` DESC LIMIT 5";
This query here is supposed to SELECT * pages where the $_GET['variables'] match the conditions. The $_GET['variables'] are $page_type = type of page AND $loc = location to search. The problem is that I have it set to LIMIT 20, but it only renders one page.
function SearchByTypeLoc($page_type, $loc) {
$query = mysql_query("
SELECT
`$page_type`.title AS title,
`$page_type`.url_title AS url_title,
`$page_type`.page_type AS page_type,
`$page_type`.street AS street,
`$page_type`.city AS city,
`$page_type`.state AS state,
`$page_type`.city_state_zip AS city_state_zip,
`$page_type`.phone AS phone,
LEFT(`$page_type`.body, 100) AS body,
LEFT(`$page_type`.type, 50) AS type,
GROUP_CONCAT( i.image_loc ) AS images
FROM `$page_type`
JOIN page_images i USING( title )
WHERE
`$page_type`.page_type = '$page_type' AND
`$page_type`.city = '$loc'
ORDER BY title
LIMIT 20");
while($fetch = mysql_fetch_assoc($query)) { ...
?>
Any idea how to make it not LIMIT 1?
GROUP_CONCAT is an aggregate function,
try explicitly add a
GROUP BY `$page_type`.title
It doesn't LIMIT 1, but there is only $page_type which matches the criteria. You join on title (why not on an id?) so there must only be one $page_type with images with a matching title.
If you want to return pages which also may not have any images then you need to change the JOIN to LEFT JOIN.
The way you link pages to images is flawed. If you change the title of a page you need to remember and update the respective title in the images table. In any case this is not a proper foreign key. You should use an auto_increment id on pages.
i have a table named IMAGES in which there is attribute name img_ID which is the primary key,
there is another table called Favorites in which there are two attributes 'img_ID' & user_ID ... img_ID serves as the foreign key to an image and user_ID serves as foreign key to the user
NOW i need details of from IMAGES of all the img_IDs from Favorites where user_ID is some x-value
this i could do like this, b.t.w i am using PHP & mySQL
$gett = mysql_query("SELECT img_ID FROM favorites WHERE user_ID='".$variable."'");
if( mysql_num_rows($gett) > 0 )
{
while( $steps = mysql_fetch_assoc($gett) )
{
$res = mysql_query("SELECT * FROM images WHERE img_ID='".$steps['img_ID']."' ORDER BY img_Date");
if( mysql_num_rows($res) > 0 )
{
while( $result= mysql_fetch_assoc($res) )
{
echo $result['img_Name'];
echo $result['img_Desc'];
echo $result['img_ext'];
}
else
echo "no images were found";
}
}
else
echo "no favorites were found";
THE PSEUDO CODE will be like
RUN QUERY
for each img_ID where user_ID is this
RUN QUERY
for each img_ID
perform DISPLAY
This methodology has a flaw & a back-draw
FLAW = the order which is on time stamp is destroyed
back-draw = there is a query in nested loop..
QUESTION: Can this all be done in with query? if Yes then How ?
Use a join:
select
i.*
from
favorites f
join images i on f.img_id = i.img_id
where
f.user_id = <user id>
Also, change your code to use mysqli and prepared statements with bind variables to both improve performance and eliminate the threat of sql injection attacks.
SELECT i.* -- possibly would need to be "SELECT DISTINCT i.*" instead
FROM images AS i
INNER JOIN favorites AS f
ON f.img_ID = i.img_ID
WHERE f.user_ID = ???
No loops, just query both tables.
SELECT
images.*
FROM
images
INNER JOIN
favorites
ON
favorites.img_ID = images.img_ID
WHERE
favorites.user_ID = X