I'm building a forum, and I have a problem with a SQL select with many joins. I want to show two images of different users in the same row.
The first image of the user is who wrote the topic, and the second image is of the user who last replied.
The query I build:
SELECT
posts.*, users.photo, users.displayname FROM posts
JOIN users ON(posts.useraid = users.id)
JOIN users ON(posts.lastreply = user.id)
WHERE forumid='$forumid' and type='post' ORDER BY `timee` DESC
posts.lastreply = the ID of the last reply user.
You have to specify an alias for each table using the AS keyword:
SELECT posts.*,
u1.photo AS creatorPhoto, u1.displayname AS creatorName,
u2.photo AS replierPhoto, u2.displayname AS replierName
FROM posts
JOIN users AS u1 ON(posts.useraid = u1.id)
JOIN users AS u2 ON(posts.lastreply = u2.id)
WHERE forumid= #forumid and type='post'
ORDER BY `timee` DESC
Notice how I call each instance of the users table by a different name - u1 and u2. Also notice how I have specified a column alias to distinguish between the two columns of the same name (e.g. creatorPhoto and replierPhoto). This way you can use the name as an index into a PHP associative array a la $post['creatorPhoto'].
Yes, I've silently changed your inline variable to a parameter. Take it as a hint. :-D
In addition to the lack of aliases in the from clause you may also have a problem with the where and order by clause. You need to use aliases for the columns there.
I don't know where they come from, but something like:
WHERE posts.forumid='$forumid' and posts.type='post'
ORDER BY posts.`timee` DESC
Assuming all come from posts.
you need an alias for this to work
SELECT
posts.*, u1.photo, u1.displayname, u2.photo, u2.displayname FROM posts
JOIN users u1 ON posts.useraid = u1.id
JOIN users u2 ON posts.lastreply = u2.id
WHERE forumid='$forumid' and type='post' ORDER BY `timee` DESC
SELECT posts.*, author.photo as author_photo, author.displayname as author+name,
replier.photo as replier_photo, replier.displayname as replier_name
FROM posts
JOIN users author ON(posts.useraid = users.id)
JOIN users replier ON(posts.lastreply = user.id)
WHERE forumid='$forumid' and type='post' ORDER BY `timee` DESC
Related
I have 3 tables - users, journals, journaltags. I select data from 3 tables using chosen tags.
$sqltheme="SELECT users.id as uid, users.name, users.surname, users.avatar, journals.id, journals.author_id, journals.title, journals.text, journals.create_date, journaltags.name as jname FROM users
INNER JOIN journals ON users.id=journals.author_id
INNER JOIN journaltags ON journaltags.journal_id = journals.id WHERE journals.create_date LIKE ? AND journals.author_id=? AND (".$expression.") ORDER BY journals.id DESC LIMIT 10";
$stmtheme=$conn->prepare($sqltheme);
$stmtheme->execute($array);
But if two tags is the same for one journal then it is selected the same journal two times. How can I make DISTINCT journals.id. I tried GROUP BY journals.id but it didnt help.
If I understand correctly, your problem is that the journaltags table may have one or more rows with a duplicated journal_id and name column value, right?
You can simply add a distinct clause to your select statement, after the word SELECT:
SELECT DISTINCT users.id as uid, users.name, users.surname, users.avatar, journals.id, journals.author_id, journals.title, journals.text, journals.create_date, journaltags.name as jname FROM users
INNER JOIN journals ON users.id=journals.author_id
INNER JOIN journaltags ON journaltags.journal_id = journals.id WHERE journals.create_date LIKE ? AND journals.author_id=? AND (".$expression.") ORDER BY journals.id DESC LIMIT 10
The reason that your GROUP BY journals.id did not work, is because you had other columns that needed to be included in the grouping as well. Adding distinct is essentially a short way of writing group by [all selected columns]
I have two tables: publick_feed and users
I want to SELECT all from public_feed and also SELECT a three columns from users whose id is the same of user_id in public_feed
and assign the rows returned from public_feed to the column in users table ( correspondent)
I try this:
<?php
$sql = "
SELECT * FROM public_feed
WHERE user_id IN
(SELECT id FROM users) AND
(SELECT Firstname,Lastname,Avatar FROM users WHERE id IN(SELECT user_id FROM public_feed))
";
$query = mysqli_query($dbc_conn,$sql);
if(mysqli_num_rows($query) > 0){
while($row = mysqli_fetch_assoc($query)){
//echo rows with correspondent details from the users table
echo $row['user_id'];
}
}
<?
Please any help will be much appreciated.
Thank you.
Or version with left join in case if there is no user in public_feed, and you still want to fetch user data
SELECT
u.*, f.*
FROM
public_feed f LEFT JOIN
users u ON f.user_id = u.id;
Because author asked for explanation, here it is:
First we are going to use table name alias to make query shorter
public_feed f
and
users u
we are saying that want to refer to tables with an alias. Of course * means that we want to select all columns
SELECT users.*, public_feed.*
is equal to
SELECT u.*, f.*
Of course you can use any other letters as an alias
Next we are saying that public_feed.user_id must be equal to users.id. But when public feed entry does not exists just display columns with null values. This is why we are using LEFT JOIN instead of INNER JOIN. In general JOINS are used to fetch related data from more than one related tables.
ON keyword is saying values from which columns in the tables must be equal to satisfy the request
I think doing a join would be cleaner than using a complicated subquery:
SELECT u.Firstname,
u.Lastname,
u.Avatar,
COALESCE(pf.User_id, 'NA'),
COALESCE(pf.Post, 'NA'),
COALESCE(pf.Date, 'NA')
FROM users u
LEFT JOIN public_feed pf
ON u.Id = pf.User_id
I chose a LEFT JOIN of users against public_feed on the assumption that every feed will have an entry in the users table, but not necessarily vice-versa. For those users who have no feed entries, NA would appear in those columns and that user would appear in only a single record.
I am currently building a custom CMS to help me learn PHP and MYSQL. I have two database tables 'users' and 'articles'. When the user submits an article, the field 'author_id' in the 'articles' table places to the users 'users_id' from the 'users' table. This way i can join the tables and get all the articles from that user. Now i am trying to make a feature section on the home page. I want to loop through all authors/users and get one article from that user. Here is a sample of my code...
$author= db::getInstance()->query("SELECT * FROM users, articles WHERE user_id = author_id");
foreach($author->results() as $author) {
echo $author->profile_img;
echo $author->user_name
echo $author->article_title;
}
This works fine if the user has only posted one article but if there are more than 1 then it will loop through all the posts of that user. I just want to echo 1 article from each user but not sure how i can achieve this. Can anyone point me in the right direction?
Many Thanks,
Louis Lombardi
If you want one arbitrary article for each user, you can use a MySQL (mis)feature that allows you to do "partial" aggregations:
SELECT u.*, a.*
FROM users u JOIN
articles a
ON u.user_id = a.author_id
GROUP BY u.user_id;
My preferred method for a random article would be more like this:
select u.*, a.*
from (select u.*,
(select a.article_id
from articles a
where a.author_id = u.user_id
order by rand()
limit 1
) as article_id
from users u
) u join
articles a
on u.article_id = a.article_id;
Finally, my preferred method for getting the first/last would look something like this:
SELECT u.*, a.*
FROM users u JOIN
articles a
ON u.user_id = a.author_id
WHERE a.article_id = (SELECT MAX(a2.article_id)
FROM articles a2
WHERE a2.author_id = u.author_id
);
You can use MySql limit:
SELECT * FROM users, articles WHERE user_id = '$author_id' limit 0,1
Complete documentation: https://dev.mysql.com/doc/refman/5.5/en/limit-optimization.html
I got two tables, customer_ledger and users.
I'm using PHP for my simple log-in program wherein the users input their username and password. Once the account is valid, it will show them their billing history. So I joined the two tables to link the username with the contract number in the other table.
My problem now is, how to display their (5) latest billings based on the field (LDGR_PER_COV_TO)? I created a MySQL query but it gave me a different result.
This is my query:
SELECT
customer_ledger.LDGR_YEAR,
customer_ledger.LDGR_MONTH,
customer_ledger.LDGR_PER_COV_FROM,
customer_ledger.LDGR_PREV_RDNG,
customer_ledger.LDGR_PER_COV_TO,
customer_ledger.LDGR_PRES_RDNG,
customer_ledger.LDGR_KWH_USED,
customer_ledger.LDGR_BILL_AMOUNT
FROM
customer_ledger
INNER JOIN users
ON customer_ledger.LDGR_CONTRACT_NO=users.LDGR_CONTRACT_NO
WHERE users.Username = 'kim'
ORDER BY customer_ledger.LDGR_PER_COV_TO ASC
LIMIT 5
this result will give me rows starting from the top most record. I would like it to display from the bottom-going up (latest record - top record).
Can anyone help?
You should use alises for better readibility,
Then use DESC in place of ASC
SELECT cl.LDGR_YEAR, cl.LDGR_MONTH,
cl.LDGR_PER_COV_FROM, cl.LDGR_PREV_RDNG,
cl.LDGR_PER_COV_TO, cl.LDGR_PRES_RDNG,
cl.LDGR_KWH_USED, cl.LDGR_BILL_AMOUNT
FROM customer_ledger AS cl INNER JOIN users AS u
ON cl.LDGR_CONTRACT_NO=u.LDGR_CONTRACT_NO
WHERE u.Username = 'kim'
ORDER BY cl.LDGR_PER_COV_TO DESC LIMIT 5
New Query ::
SELECT * FROM
(
SELECT cl.LDGR_YEAR, cl.LDGR_MONTH,
cl.LDGR_PER_COV_FROM, cl.LDGR_PREV_RDNG,
cl.LDGR_PER_COV_TO, cl.LDGR_PRES_RDNG,
cl.LDGR_KWH_USED, cl.LDGR_BILL_AMOUNT
FROM customer_ledger AS cl INNER JOIN users AS u
ON cl.LDGR_CONTRACT_NO=u.LDGR_CONTRACT_NO
WHERE u.Username = 'kim'
ORDER BY cl.LDGR_PER_COV_TO DESC LIMIT 5
) AS a
ORDER BY a.LDGR_PER_COV_TO
I need to alter my existing JOIN query below to also include the data from users.image correlating to the UserID of the post maker. Something like:
users.image WHERE users.UserID = posts.userid
I am not very good with join queries yet. How would I do this?
Existing Query:
$result = mysql_query("SELECT posts.* FROM listen JOIN posts ON posts.userid = listen.listenid WHERE listen.userid = '$user_id' ORDER BY DATE desc") or die(mysql_error());
Just add another JOIN clause:
SELECT posts.*
FROM listen
JOIN posts ON (posts.userid = listen.listenid)
JOIN users ON (users.UserID = posts.userid)
WHERE listen.userid = '$user_id'
ORDER BY DATE desc
You may need to change the JOIN to a specific join such as LEFT JOIN, depending on what you're after.
Btw, it is easier to see the query on multiple lines.
Edit: You'll probably want to add additional items that you are selecting with your fields, such as SELECT posts.*, users.*