I am making a cookie based favorite system and need to join data from two tables based on the unique user id stored in the cookie so I can tell what items that use has marked as favorites.
I know I need to do a JOIN but have not used them much and dont really have my head around them yet.
Existing query that selects the items from the db:
$query = mysql_query("SELECT *, UNIX_TIMESTAMP(`date`) AS `date` FROM songs WHERE date >= DATE_SUB( NOW( ) , INTERVAL 2 WEEK ) ORDER BY date DESC");
My favorites table is setup as: ID FAVORITE USERID where ID is the primary key, FAVORITE is the song ID from table songs and USERID is a hash stored in a cookie.
I need to join in all the rows from the favorites table where the USERID field matches the cookie hash variable.
I also need to gather the total number of rows in favorites that match the song id so I can display a count of the number of people who set the item as favorite so I can display how many people like it. But maybe need to do that as a separate query?
This should do it, I would imagine:
$user_id = intval($_COOKIE['user_id']);
$query = mysql_query(sprintf("
SELECT *
FROM songs s
INNER JOIN favorites f
ON f.favorite = s.id
WHERE f.userid = %s
", $user_id));
You should probably read up on the different types of joins.
And then to get the total amount of rows returned, you can just call mysql_num_rows on the result:
$favorite_song_count = mysql_num_rows($query);
EDIT: To select all songs but note which are favorited, you would do this:
$query = mysql_query(sprintf("
SELECT s.*, f.id as favorite_id
FROM songs s
LEFT JOIN favorites f
ON f.favorite = s.id AND f.userid = %s
", $user_id));
By switching it from an INNER JOIN to a LEFT JOIN we are selecting all songs even if they don't have a corresponding record in the favorites table. Any songs that are favorites of the user_id provided will have a non-NULL value for favorite_id.
You can have logical (and, or, ...) operators in join conditions:
select t1.*
from t1
join t2 on t1.id = t2.fid and t2.foo = 'blah'
If you are also querying the total number of times each song has been "favorited" then you need a group by construct also, like this way:
select *, count(f.id)
from songs as s
left join favorites as f on s.id = f.favorite and f.userid = <hash>
group by s.id
Related
table posts
table users
how would i count posts for specific user logged in. for example when user with id 3 is logged in it should show me 4 posts
I already did it for total posts count:
<?php
$post_query1 = "SELECT count(*) AS total FROM posts ";
$post_result1 = mysqli_query($db, $post_query1);
$post1 = mysqli_fetch_array($post_result1);
?>
Try below example :
select count(*) as total from user as u inner join post as p on p.id_user = u.id_user AND u.id_user = 3
If you want to get only the posts count for the particular user, say user with id = 3, your query should be this:
$query = "SELECT count(*) AS total FROM posts WHERE id_users = 3";
But if you want to get both the posts count as well as the user information and other post information, you will have to run a join query on both the users and posts table. Your query would now become:
$query = "SELECT u.*, p.*, count(p.id_posts) FROM users AS u JOIN posts AS p ON u.id_users = p.id_users WHERE p.id_users = 3";
Some Useful Notes
p.* - * is a wildcard character that means get all the columns in the posts table
u.* - * is a wildcard that means get all the columns in the users table
posts as p - AS is for aliasing. So, we are giving posts table a temporary name.
Here are the different types of the JOINs in SQL:
(INNER) JOIN: Returns records that have matching values in both tables
LEFT (OUTER) JOIN: Return all records from the left table, and the matched records from the right table
RIGHT (OUTER) JOIN: Return all records from the right table, and the matched records from the left table
FULL (OUTER) JOIN: Return all records when there is a match in either left or right table
Note: It is necessary that you have to join two/more tables only with the help of foreign key. Without the foreign key is is meaningless to join two or more tables
Reference 1: https://www.w3schools.com/sql/sql_join.asp
Reference 2: https://www.tutorialspoint.com/mysql/mysql-using-joins.htm
As per the Question what you have asked to join the tables
Query:
SELECT * FROM TABLE 1 JOIN TABLE 2 ON TABLE1.id = TABLE2.id WHERE TABLE2.ID=3
Kindly replace TABLE1 & TABLE2 with the Tables that are to be joined and the id with the foreign key what you have specified in the Table.
Hope so this might be helpful for you to write your own code in future. Happy Coding :)
You have only to use a simple join.
SELECT count(*)
FROM USER u,
post p
WHERE p.id_user = u.id_user
AND u.id_user = 3
I have an articles table that and I am displaying it in the homepage in a while loop. Inside the while loop I want to display the comments count and images count for each article.
It is working for me now, but it is three queries in total, I am trying to combine it in the first query and then just display all of them in one while loop. Here is what I am trying to achieve:Articles page
The current format I am following:
//a represents articles table, c represents comments table, i represents image table
$query = mysqli_query($conn, "SELECT a.a_id, a.title, a.datetime, a.user_id FROM a ORDER BY a.datetime DESC");
while($fetch = mysqli_fetch_assoc($query){
$imageQ = msqli_query($conn, "SELECT COUNT(image_path), image_path FROM i WHERE a_id = '$fetch['a_id']'");
$imageFetch = mysqli_fetch_assoc($imageQ);
$commentQ = mysqli_query($conn, "SELECT COUNT(comment_id) FROM c WHERE a_id = '$fetch['a_id']'");
$commentFetch = mysqli_fetch_assoc($commentQ);
}
I want to cram all of these queries into one single query that fetches the article and comments count and image count for each article and the first image.
The images and comments are separate dimensions of the data. So, you have to be careful about how to bring them together. In your case, you can aggregate the values before doing the joins:
SELECT a.a_id, a.title, a.datetime, a.user_id,
i.num_images, c.num_comments
FROM a LEFT JOIN
(SELECT a_id, COUNT(image_path) as num_images
FROM i
GROUP BY a_id
) i
ON i.a_id = a.a_id LEFT JOIN
(SELECT a_id, COUNT(comment_id) as num_comments
FROM c
GROUP BY a_id
) c
ON c.a_id = a.a_id
ORDER BY a.datetime DESC;
You can use mysql nested queries something like
SELECT a.,tab1.,tab2.* FROM a INNER JOIN (SELECT * FROM b ) as tab1 INNER JOIN (SELECT * FROM c) as tab2
Hope this can get you to get desired output.
Thanks
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 have two tables,
TABLE 1 has many of each client and campaign and is very large
TABLE 2 has only one of each client and campaign and is small.
So I want to get the lastest(highest ID) from TABLE 1 where it matches the client and campaign in TABLE 2 and only one of each.
I have tried MAX, and playing with the order by etc, but cant get it working....
The results I get are choosing the lowest ID from TABLE 1 (I want highest)
$result2 = mysql_query("SELECT table1.client,table1.campaign,table1.id
FROM table1
LEFT OUTER JOIN
table2
ON (table2.client = table1.client)
AND (table2.campaign = table1.campaign )
WHERE (table2.enabled != 'disabled')
group by campaign asc
order by client,campaign,id asc
");
Help needed....
SELECT * FROM table1
INNER JOIN
(
SELECT MAX(table1.id) AS id FROM table1
INNER JOIN table2 ON table2.client = table1.client AND table2.campaign=table1.campaign and table2.enabled != 'disabled'
GROUP BY table1.client, table1.campaign
) AS m ON m.id = table1.id
I think that's what you're asking for. For each combination of client and campaign that exists in each table, it will give you the highest ID in table 1.
Im trying to construct a query that goes over 3 tables and im COMPLETELY stumped ... my knowledge limit is basic 1 table query and i need some help before i stick my head in a blender.
I have the following query
SELECT * FROM internalrole WHERE introle = $imarole
Im fine with that part .. its the next thats getting me all stressed.
That query returns the following columns ( id, user_id, introle, proven, used )
What i then need to do is take the user_id from the results returned and use it to get the following
SELECT * FROM users WHERE id = user_id(from previous query) AND archive = 0 and status = 8
I need to put that into 1 query, but wait, theres more .... from the results there, i need to check if that user's 'id' is in the availability table, if it is, check the date ( column name is date ) and if it matches todays date, dont return that one user.
I need to put all that in one query :S ... i have NO IDEA how to do it, thinking about it makes my head shake ... If someone could help me out, i would be eternaly grateful.
Cheers,
Use INNER JOIN, which links tables to each other based on a common attribute (typically a primary - foreign key relationship)
say an attribute, 'id', links table1 and table2
SELECT t1.att1, t2.att2
FROM table1 t1
INNER JOIN table2 t2
ON t1.id = t2.id --essentially, this links ids that are equal with each other together to make one large table row
To add more tables, just add more join clauses.
SELECT u.*
FROM internalrole ir
INNER JOIN users u
ON ir.user_id = u.id
AND u.archive = 0
AND u.status = 8
LEFT JOIN availability a
ON ir.user_id = a.user_id
AND a.date = CURDATE()
WHERE ir.introle = $imarole
AND a.user_id IS NULL /* User does NOT exist in availability table w/ today's date */
EDIT: This second query is based on the comments below, asking to show only users who do exist in the availability table.
SELECT u.*
FROM internalrole ir
INNER JOIN users u
ON ir.user_id = u.id
AND u.archive = 0
AND u.status = 8
INNER JOIN availability a
ON ir.user_id = a.user_id
WHERE ir.introle = $imarole
Hmm, maybe something like this
SELECT * FROM users WHERE id IN (SELECT user_id FROM internalrole WHERE introle = $imarole) AND archive = 0 and status = 8;
A handy thing for me to remember is that tables are essentially arrays in SQL.
HTH!
Nested queries are your friend.
SELECT * FROM users WHERE id in (SELECT user_id FROM internalrole WHERE introle = $imarole) AND archive = 0 and status = 8
Alternatively joins:
SELECT * FROM users INNER JOIN internalrole ON users.id = internalrole.user_id WHERE internalrole.user_id = $imarole AND users.archive = 0 and users.status = 8