So I have 3 tables: users, posts, private. In this example, lizzy created a private post 'Dating' and only wants her girlfriends to see it 'authorized_user_ids' in the private table, and herself 'user_id' in posts table.
users
user_id user_name
1 tony
2 steph
3 lizzy
4 adam
5 lara
6 alexa
posts
post_id user_id post_name private (0 is public, 1 is private to authorized users)
1 1 Coding 0
2 3 Dating 1
3 3 Show Me 0
private
private_id post_id authorized_user_ids
1 2 2,5,6
Only the private poster user_id and the authorized_user_ids should see the 'Dating' post by lizzy, but everyone should be able to see the 'Show Me' post by lizzy. Logged out users and users not authorized should not see anything. Is that the most efficient way to go about it, or should it be:
private
private_id post_id authorized_user_id
1 2 2
2 2 5
3 2 6
That's my first question. My second is what would be the best way to tackle it in php (display to authorized_user_ids) when pulling the data from a mysql db? Do we do a second query based on the 'private' flag in the posts table? If it is 1, we query in the while loop to get the 'authorized_user_ids' from the private table, and if it matches the $logged_in_id of the logged in user, then we display 'Dating'? Or should there be a join somewhere in the main query with the 'authorized _user_ids' using the 'post_id' in the private table and the posts table? Any help on how to most efficiently do this is appreciated.
First Q: I would definitely go with the second version. Storing authorized_user_id as a CSV will cause both DB read and write operations to become much less efficient as you will end up splitting the CSV values all the time in your application code and generating bad dynamic SQL statements in order to process updates. You should never have to write PHP code to help with finding the intersection of different sets of data like that, use SQL.
Second Q: Use joins, no while loops for example
SELECT DISTINCT p.post_id, p.post_name FROM users as u
JOIN posts as p on p.user_id=u.user_id
LEFT JOIN private pv on pv.post_id=p.post_id
WHERE (p.private=0) OR (authorized_user_id={$logged_in_id} and p.private=1)
The above (or very similar) will list all posts $logged_in_id is 2 but only public ones when $logged_in_id is 4 etc.
Related
I have this table
myid his_id
7 1
1 7
1 6
1 3
But its giving me 4 records instead of 3, i tried using mysqli "join" , "group by" but didnt work.
Im trying to develop a chat system with pure php and jquery, in d table above, user 7 chatted with user 1 and user 1 chatted with user 7 so i want to see it as just the same chat and the rest of the 2 ( user 1 chatting with user 6 and user 1 chatting with user 3)
I want it to give me just 3 records instead of 4 records, pls any help will be appreciated, thank you
Sorry im not connected to my system, im using a smart phone, forgive my bad formatted query below
$sql = mysqli_query($connectn, "select a.id, b.his_id, a.myid, a.status, a.date_replied FROM chats a JOIN chats b ON b.myid=b.myid WHERE b.his_id='$regestered_id' or b.myid='$regestered_id' GROUP BY b.his_id ORDER BY a.id DESC") ;
If you want distinct combinations of myid and his_id, you must not print id, date_replied, status, etc, but just two columns- his_id, myid.
Because if there are multiple rows with two columns with same values, it is yet another to decide which row must be selected in order to print id, status, etc.
So, just to print which two users are chatting, use myid and his_id. You can later use them for any other information.
Now, the code you wanted is-
$sql = mysqli_query($connectn, "select distinct
least(myid, his_id), greatest(myid, his_id)
from chats");
And yes, like #iblamefish mentioned, don't forget to protect your code against SQL injection.
I am trying to create an algorithm to sort out the most relevant data for a specific user_id.
I imagine my end result to be an array with KEY as the found USER_ID and the VALUE to be the number of times the specific USER_ID has been found in the different rows.
So, I need to look through different rows in different tables and look for where CURRENT_USER_ID (lets say id: 30) exists, and then find the RECIEVER_ID, that is the user which was communicated to. This is pretty hard to explain, but lets take an example:
I have a table called: edu_posts, which contains wallposts and comments to theese. The are different values in this table, but the ones we should focus on is: post_author and post_reciever. We then have to look for all the rows where post_author equals 30 (the test example; just needs to be the current users id) and then print out the post_reciever IDS. This would be easy enough with a single query, but lets say we have to find data in 5 or 10 different tables, that 10 different queries, which is a lot.
We also have a table called edu_folowers. There we have to look for where follow_author equals 30 (the test example; just needs to be the current users id), and then print out the follow_user ID. Again, to find out who the current user have interest in.
I image the final mysql_fetch to look something like this:
user_id => 25
times_found => 5
user_id => 11
times_found => 3
user_id => 95
times_found => 1
etc.
Can this be done using a single query, maybe using JOIN? And even maybe count the results IN the query, so I don't have to do this manually in the PHP code.
Or should I create a mysql_query for every table I wish to get data from, and then manage the data afterwards using PHP? This sounds like the easiest way to me, but also the most inefficient relating to script optimization.
I have tried out with the following test-query:
SELECT
u.user_id AS user_id,
f.follow_user AS user_id_follow,
p.post_reciever AS user_id_posts
FROM
`edu_posts` u
LEFT JOIN `edu_followers` f ON f.follow_author = '30'
LEFT JOIN `edu_posts` p ON p.post_author = '30' && p.post_reciever != '30'
WHERE
u.user_id = '30'
GROUP BY
f.follow_id, p.post_id
But the problem is that it outputs unexcepted results, and also I will have different values to look for, fx: user_id (not really needed, as we already know that it is 30), user_id_follow, user_id_posts, and so on.
I hope you understand my question, and please let me know, if you need additional information.
Many thanks in advance!
You could create a union view of all of the tables that you want to search, depending on your exact requirements you might only need to query that once.
e.g.
create view allPostTypesUnion as
select user_id, post_receiver
from edu_posts
union
select user_id, post_receiver
from different_edu_posts
union
select user_id, post_receiver
from another_different_edu_posts
then:
select post_receiver, count(*)
from allPostTypes
group by post_receiver
The query below selects the 'loves' on an item. (think of it as similar to facebooks 'like' system.
There are two tables in use in this select. A link table (containing itemid, userid, lovetime) and this is joined to a users table in order to retrieve the username/user profile url etc.
$lovequery = "select love.lovetime, love.userid as ID, love_users.display_name, love_users.user_url
from ".$wpdb->prefix."comment_loves love
left join ".$wpdb->prefix."users love_users on love_users.ID=love.userid
where commentid = $itemid
order by love.lovetime desc
limit 4
";
The results are limited to 4 because I simply do not need any more data. The total count is stored separately in the actual item table to reduce queries.
Once the rows are retrieved from this query I iterate through the array, cross referencing against the total 'lovecount' and build a text string formatted like so:
You, John Smith, Joe Bloggs and 4 others love this.
This works fine however it fails if the logged in user (YOU) does not have the most recent 'lovetime'
What I want to do is have the currently logged in use always at the top of the returned results even if his/her 'lovetime' is older than the 4 most recent ones so that the string always begins with 'You' if the logged in user has 'loved' this item.
The logged in user id is available in the script as $userid.
To clarify
if I have the following table (the timestamps are written as simple UK dates for legibility purposes):-
userid commentid lovetime
34 3 02/10/2011
24 3 03/10/2011
13 3 06/10/2011
65 3 14/10/2011
1* 3 10/09/2011
* with userid 1 being the logged in user id
I would only get user id's 34,24,13,65 returned in that order due to ordering by 'lovetime'
What I want is for the results to return ideally 1,34,24,65. if that proves too tricky then getting 5 total rows when the userid exists would be okay also.
I hope this is clear enough, it was rather difficult to articulate.
How would I go about modifying the query to ensure the results are as described.
Many thanks.
You can order result by condition like ORDER BY (ID = "auth_user_id") DESC
I'm trying to come up with the most simple / userful / efficient method to group 3 users together using mysql.
To set the stage:
X number of users in a list (all with int account_id's)
mini groupings need to be created on a per user basis (user 1 wants to group with 220 for instance).
Max 3 people per grouping (user 1 + user 220 + user 9123 = group full)
Need to easily find if a user is in a group or not without looking in a bunch of columns
I'm stumped about how best to create a schema for this (so I can easily query my table to see if user is in a group, or if they can be added, or check for group space availability).
Anyone have any idea? My initial thought is schema like this (but it really seems too rigid):
Schema
GROUP_ID USER1 USER2 USER3 LASTUPDATE
1 1 220 null 5/25/2011 20:00:00
2 300 2 4 5/25/2011 20:00:00
How would you do it to make something this simple very flexible and efficient. I really feel stupid for asking.
Personally I would approach this by using 3 tables.
Users Table
user_id user_name ..... last_update
Groups Table
group_id group_name ......
Users to groups Table
user_to_group_id user_id group_id
This forms a many to many relationship by linking through the "Users to groups" table, obviously you can have more that 3 users linked to one group so you will have to make your PHP logic check for this when adding a new user to a group.
You can simply use SQL joins to retrieve all the data required and filter the results in your PHP code.
I hope this helps
Kind regards
Garry
I've got an small issue, I'm trying to make my own forum, but I am stuck at something.
I have 3 tables, 1 users with a user_level (Authentication level).
forum_section which contains all the sections with a user_level again.
But how can I link forum_section.user_level to forum_topics.user_level.
So if I define: forum_section.user_level = 4 for forum_section.section_id = 1.
For example:
Someone wants to visit the forum_section id 1 then they must have a auth level of 4.
And when they go to the topic it then again checks if the user level is 4, but I do not want to manual set the topic level, topic level must always be the same as the section level.
I've googled for this, but I can't really find a good manual for it. I guess it has something to do with: "foreign keys"?
Okay, let me explain a bit more just to be sure.
I have 3 tables
Table User
username = Wesley
userlevel < for example 4(admin).
Table section
section_id = 3
section_name = News
section_level = 3 <require level to view.
table topics
topic_id = 123
topic_name = I like candy
topic_level = Needs to be the same as section_level so if I change section_level it automatically changes this too.
You should have to manage your database by using master and transaction tables.
Your table format should look like this:
table name: user
user_id user_name
1 abc
2 xyz
3 pqr
4 new
table2 name : forum_section
forum_id user_id forum_name
1 4 abc
2 4 jkl
3 2 cbd
4 3 lmn
Now, you can JOIN these two tables and make a query as you want, like this:
SELECT forum_id FROM forum_section as fs,user as u WHERE fs.user_id = u.user_id AND fs.user_id = 4
This may help you. Please write if you need more help!
You need to either use a SQL JOIN or a NESTED SUB QUERY
The simplest implementation would be to initially establish the users access level, then filter subsequent queries based on this- so in your PHP, pass the access level to subsequent requests for content- if the query returns anything, the user can view the content, if not- they can be redirected.