php, MySql subquery from two tables - php

I'm trying to build a MySql query to produce results based on following:
Table Permissions
user_id blog_id
=========================
1 1
1 2
1 3
2 2
3 1
Table Blog
id name
=========================
1 First Blog
2 Second Blog
3 Third Blog
4 Fourth Blog
I need to select all the records from Blog table and display it based on logged in user id like:
$user_id = $_SESSION['user_id];
Table Permissions contains access for each user allowed to view results from blog table.
So something like:
"SELECT * FROM Blog WHERE id IN()"
but I'm not sure how to access permission table to use it in IN().
So for example if user with id 1 is logged in, this user should be able to see Blogs with matching id's 1,2 and 3.

You can use either a join, or an in() subquery.
select b.* from blogs b
inner join permissions p
on b.id=p.blog_id
where p.user_id=...

Try this:
SELECT * FROM Blog INNER JOIN Permissions ON Permissions.blog_id = Blog.id
This show all users.
Working code here: http://sqlfiddle.com/#!9/aa3e9/14
You can use:
SELECT * FROM Blog INNER JOIN Permissions ON Permissions.blog_id = Blog.id
WHERE Permissions.user_id = 'user_id number'
To get a specific user.

Related

Getting data from multiple mysql tables WHERE.

I have 2 database tables.
One called files. Which looks like this.
FILES
USERID FILENAME DEFAULT NETWORKID
88 hello 1 10293
9 bob
43 opener 1 10293
43 facepa
9 closer
Second table user networks
USERID NETWORKID
9 10293
43
My current sql query is
SELECT file,filename,filetype,size, forename, files.userID
FROM (`files`)
LEFT JOIN users ON users.userID = files.userID
WHERE files.userID = $userID ORDER BY id DESC
This currently gets the list of files where userid is 9.
As you can see my userid 9 is also in the usernetworks table and I am connected with network id 10293.
I want to also include in the query, any of the rows that default is 1 and the network id matches to any of those in the usernetworks table with my userID.
So where userid is connected to networkid, also show those results aswell as the ones with userid and no network id.
Any help appreciated.
If I read your logic correctly, then we can implement it by first left joining files to users on the condition that the user matches to your user ID. Then, we can left join again to users, this time on the condition that the file record is default, the network IDs match, and the matching user is also your user.
SELECT f.*
FROM files f
LEFT JOIN users u1
ON f.userID = u1.userID AND f.userID = $userID
LEFT JOIN usernetworks u2
ON f.default = 1 AND
f.networkid = u2.networkid AND u2.userID = $userID
WHERE
u1.userID IS NOT NULL OR u2.userID IS NOT NULL;
Actually, if you don't plan on selecting any columns from the users table then you can probably omit the join to that table completely. I have left it in as it is true to the original query in your question.
I understand you want your files plus the default files in your networks:
SELECT userid, filename, networkid
FROM files
WHERE (userid = $userid
OR (default = 1 AND networkid in (
select networkid from network_users where userid = $userid)))
AND filename like :name
Your SQL mentions fields that are not in your schema description.
If you want to get the data on the basis of network id than please use this query
SELECT file,filename,filetype,size, forename, files.userID
FROM files a, network b
WHERE a.networkID = b.networkID ORDER BY id DESC
.
Hope this will solve your problem

Mysql SELECT name where all rows with the name have certain values

How would I write a query that would select the name of a person (a column in the row) given that they have enough rows to meet all conditions?
For example, I have a database set up like so:
name permission_id
Bob 1
Bob 2
Jerry 3
Jerry 1
Jose 2
Billy 1
Billy 2
How would I only select the people that have permission id 1 and 2? In other words, I would like a query that checks every person by name to see if they have all the permissions requested.
In this example if I was to check for all users to who have permission 1 and 2 I should get Bob and Billy as a return value.
Here is my current query:
$this->db->select('center_user_permissions.id, center_users.first_name, center_users.last_name');
$this->db->from('center_user_permissions');
$this->db->where_in('permission_id', $permission_ids);
$this->db->join('center_users', 'center_users.center_id = center_user_permissions.center_id');
Currently this query returns anybody who has either permission id 1 or 2. I need it to be 1 AND 2. But I know I can't simply make two wheres because one particular row can't have both permission ids, but the query must check all rows for the specified ids.
I believe I would need a SELECT statement inside of my where? Can anybody tell me if I'm thinking correctly? Thanks.
You can use a in clause an an having for check that the user has both the permission
select name
from center_user_permissions
where permissions_id in (1,2)
group by name
having count(*) = 2
I'm not sure how to build this query in CodeIgniter, but you could INNER JOIN for each permission ID you want the user to have:
SELECT center_users.center_id, center_users.first_name, center_users.last_name
FROM center_users
INNER JOIN center_user_permissions AS p1 ON p1.center_id=center_users.center_id AND p1.permission_id=1
INNER JOIN center_user_permissions AS p2 ON p2.center_id=center_users.center_id AND p2.permission_id=2
You could check for more permissions by adding a INNER JOIN for each additional permission you wanted to require.
MySQL's GROUP BY and HAVING
Not user what kind of DB interface you're using in $this->db, but it may make things a little tricky. If I start with a raw SQL query:
SELECT
center_user_permissions.id,
center_users.first_name,
center_users.last_name
FROM center_user_permissions
LEFT JOIN center_users
ON center_users.center_id = center_user_permissions.center_id
WHERE center_user_permissions.permission_id in (1,2)
Group by name, where count of permission_id is > 1
This will group rows by first_name (so you'll only get one row for each unique name). Doing do allows you to run aggregate functions (SUM(), MAX(), COUNT()) against the rows that were "grouped" into a single row.
SELECT
center_user_permissions.id,
center_users.first_name,
center_users.last_name
FROM center_user_permissions
LEFT JOIN center_users
ON center_users.center_id = center_user_permissions.center_id
GROUP BY center_users.first_name
WHERE center_user_permissions.permission_id in (1,2)
HAVING COUNT(center_user_permissions.permission_id)>1
select distinct(name),.. as name from 'center_user_permissions',center_users where
center_users.center_id = center_user_permissions.center_id and permissions_id in (1,2)
substitute .. with your other fields and put in distinct the value that you want to be unique

Retrieving aggregated results from two queries

I am trying to figure out best way to compare results from 2 queries and display the difference.
Table 1 = User Table
Table 2 = Page Table
Table 3 = Assigned table
Example:
There are users 1 and users 2 in the user table.
User 1 has been assigned to 10 pages, user 2 has been assigned to only 1 page.
This works fine for finding which pages they have assigned, which is only 1 page for this example.
SELECT * FROM assigned_table WHERE user= 2
But I can not figure out how to get results of all the other pages it doesn't have access to.
This does not work because there is user 1 that has access to all 10, so it gets the results of all other users except user2
SELECT * FROM assigned_table WHERE user != 2
So basically I need it to say what pages does user2 have access to, and then which pages does it not have access to and display both results separately
Any assistance would be appreciated.
Sorry if similar topic was posted elsewhere, was unable to find what I was looking for.
You should use a join for this. Here's the documentation on this https://dev.mysql.com/doc/refman/5.0/en/join.html.
Something like
select pt.pagename from `Assigned table` as at
join `Page Table` as pt
on at.pageid = pt.id
where at.user = 2
This would give you a listing of all page titles (pagename) user 2 has assigned to him/her. Your column and table names will need to be updated.
Pull all papers not assigned to specific user.
select pagename
from `Page Table`
where id not in (select pageid from `Assigned table` where at.user = 2)

Twitter-like following system

I am working on a twitter clone in PHP for school, and I have one major problem. I cannot find a way to implement a follower system. There is a table for users, and I want to add a field that holds the ids of all of the users that each user follows.
Should I separate the ids with commas and then split them apart in PHP? And then I need to select all of the tweets from the tweets table that were tweeted by any of the users followers. Is there an SQL command that I can use? Something similar to
SELECT *
FROM tweets
WHERE author='$followeduser'"
but where $followeduser is multiple ids.
Have a USER_MASTER table like this
USER_ID (int)
USER_NAME(varchar(50))
Create a table called USER_FOLLOWERS like this
USER_FOLLOWER_ID // Auto increment-Primary Key for this record
USER_ID (int) // foriegn key to UserId column in USER_MASTER table
FOLLOWER_ID (int) // foriegn key to UserId column in USER_MASTER table
Store the UserId in the first column and store the UserId of the User who follows this user in the Follower_ID column.
So your data will look like this
USER_ID USER_NAME
--------------------------------------
1 SCOTT
2 JARED
3 MARC
4 ERIC
USER_FOLLOWER_ID USER_ID FOLLOWER_ID
--------------------------------------
1 1 2
2 1 3
3 1 4
4 2 1
So this means , The User Scott has 3 followers, Jared, Marc and Eric. User JARED HAS one Follower, that is SCOTT
To get the list of Followers for a user(ex : Scott (ID=1)) , you can do a Join between these 2 tables
SELECT U. USER_ID, U.USER_NAME From USER_MASTER U
INNER JOIN USER_FOLLOWERS UF ON U.USER_ID=UF.FOLLOWER_ID
WHERE UF.USER_ID=1 // 1 is the ID of SCott
Make a join table.
Putting all IDs in a list is not the normalized way and can lead to many many issues.
Have a relations table where you have one column called user and second that is following. So if user 1 is following user 3 and 5, then you would have an entree where user = 1 following = 3 and user = 1 following = 5 (use whatever ID's you want). You also have your Tweets Table where you store all tweets. Youre going to want to make a query that joins the two tables

Get Topics from multiple Category and show top ten topics with responses in mysql/php

Hi friends i am listing topics in php which may be associated with multiple category
my db schema is
topics
topic_id
user_id
topic_name
category
category_id
category_name
topic_category (for association)
tc_id
topic_id
category_id
topic_response // for results
tr_id
topic_id
response ( given in a form of 5 star rating so its in range of 1-5 always )
user_id
what i need to do is
1st ) list top ten topics based on responses ya it will be based on count of responses
i tried ->
select t.* ,count(tr.response) as votes from topics t , topic_response tr where t.topic_id=tr.topic_id group by tr.topic_id order by votes LIMIT 10
not working
2nd) user will be shown list of topic . he can choose the category in which he wants that can be multiple too.
for example
if he chooses category_id 1,2,3,4 then topics listed in this category will be listed.
i have tried to
select t.* from topics t ,topic_category tc where tc.topic_id = t.topic_id and category_id IN (1,3,2,4)
// not able to get idea on this i would prefer if i could do this in subquery since i also need to check if the user has already responded to that question .
**3) in case if i get a query working suppose .
from php side i will be getting an array of category_id from select multiple dropdown
like array(1,2,3,4)
so i was thinking how will make this query accept category id
in form of category_id IN (1,3,2,4) in mysql query**
**can i directly pass an array like
category_id IN ($ids) where $ids is an array**
i am a newbie in mysql please help me
you help will be appreciated :)
For the first question:
You have to use LEFT JOIN and match (response's topic id row) to (topic's id) then count(response's topic id) and GROUP everything by (response's topic id).
for example:
Responses Table = responses
response_id
topic_id
response_message
Topics Table = topics
id
title
content
The query is
SELECT topics.title,topics.content,COUNT(responses.topic_id) AS count FROM topics
LEFT JOIN responses ON topics.id = responses.topic_id GROUP BY count LIMIT 10
For question 2:
You can try using AND ( IN 1 OR 2 OR 3 OR 4
You can try using BETWEEN 1 AND 4
WHERE(category_id>=1&&category_id<=4)

Categories