I have 3 table on my mysql db (user, follower, post), I wrote an sql, that get all posts from the people a user followed.
sql
SELECT post.* FROM post JOIN
follower ON post.owner_user_id = follower.user_id AND
follower.follower_id = "3"
result
id | owner_user_id | content
2 | 1 | why are all my senior developers jerks?
3 | 1 | PHP7 in your face node.js
user table
id | username | password
1 | user1 | 12345678
2 | user2 | 12345678
3 | user3 | 12345678
follower table
user_id | follower_id
3 | 1
3 | 2
1 | 3
post table
id | owner_user_id | content
1 | 2 | reading a 1k+ page on mysql, do i need to?
2 | 1 | why are all my senior developers jerks?
3 | 1 | PHP7!, in your face node.js
3 | 3 | I posted
so now am trying to select post of people the user is following and the posts of the user
I tried this sql
sql
SELECT post.* FROM post JOIN
follower ON post.owner_user_id = follower.user_id AND
follower.follower_id = "3" JOIN
user ON post.owner_user_id = user.id= "3"
result
null
Please is what am trying to achieve with the sql possible,
if(possible) {"what_am_i_doing_wrong"}();
edits
user_id 3 has a post, still running the above sql returns null, was hoping if the user had no post, only post of the people the user is following is returned
select post.* from
(select user_id from follower where follower_id = 3 union select 3) blah
join post on blah.user_id = post.owner_user_id;
Try this:
SELECT Distinct post.* FROM post JOIN
follower ON post.owner_user_id = follower.user_id JOIN
user ON follower.user_id = user.id WHERE user.id = 3
You shuldn't use conditions in JOIN statement, use WHERE instead.
Related
I'm building a survey system where
A client that has many users
A user can have multiple surveys.
Client A might have users [1,2,3].
Now there's a table user_completions, which shows which users have completed my survey.
users table
+----+-----------+
| id | client_id |
+----+-----------+
| 1 | 1 |
| 2 | 1 |
+----+-----------+
user_completions table
+---------+-----------+
| user_id | survey_id |
+---------+-----------+
| 1 | 1 |
| 2 | 2 |
+---------+-----------+
How can I (in one query) see how many users have a record in the user_completion table, grouped by survey, and only for the current client
The desired result would look something like
+-----------+-------+-----------------------+
| survey_id | users | num_persons_completed |
+-----------+-------+-----------------------+
| 1 | 2 | 1 |
| 2 | 2 | 1 |
+-----------+-------+-----------------------+
I think you're missing couple of table mentioning in your question but if you really have only these 2 tables than you can achieve this with following query:
select tmp.survey_id, count(distinct tmp.user_id) completed,
(select count(distinct id) from users where client_id = 1) users
from
(select t1.*, t2.*
from users t1
join user_completions t2
on t1.id = t2.user_id
where t1.client_id = 1
)tmp
group by tmp.survey_id
I have been learning PHP and MySQL for a project and I am struggling with this part. For simplicity sake, I will only list the relevant fields (actually many more in real db) let's say I have 3 tables.
Table1
---------------------
Index | Name | email
1 | Rob | rob#email.com
2 | Kevin| kevin#email.com
3 | Amy | amy#email.com
Table2
------------------------
id | Info | Submitted
1 | Blah | 0
2 | Yada | 1
Table 3
-------------------------
id | Goal |Submitted
1 | 1 | 1
1 | 2 | 1
1 | 3 | 1
1 | 4 | 0
1 | 5 | 0
3 | 1 | 0
3 | 3 | 1
3 | 4 | 1
So, Table1 holds user information and is kinda the main table
Table2 the user inputs some data in a field and then submits for approval when ready. (I will be using the value of Submitted for functions later)
If the user has not submitted the info, there is not record. This is a 1 to 1 with Table1
Table3 The user inputs information for 5 goals. At any given time there could be 0 to max 5 goals entered for a user. The Submitted is the same for later processing. This table is Many to one with Table1. The Goal field literally shows the number 1 through 5, there is a separate field that holds the goal text, just not needed in this example.
Desired output is HTML table
Name | email | info |Goal1|Goal2|Goal3|Goal4|Goal5|
Rob | rob#email.com | Blah | 1 | 2 | 3 | 4 | 5 |
Kevin | kevin#email.com | Yada | | | | | |
Amy | amy#email.com | | 1 | | 3 | 4 | |
Not sure if the blanks are considered NULL or something else as they do not exist in the DB. I would like to put something in the field like an *. Basically the Submitted will be used for code to make the fields hyper links, so they need to be part of the query, just not in the table display, but if it would help, it can be displayed.
Name | email | info |Goal1|Goal2|Goal3|Goal4|Goal5|
Rob | rob#email.com | Blah | 1 | 2 | 3 | 4 | 5 |
Kevin | kevin#email.com | Yada | * | * | * | * | * |
Amy | amy#email.com | * | 1 | * | 3 | 4 | * |
I am using a query with left joins and group_concat, but that is not working well with the non existent data, and I cannot figure out how to include the Submitted field without doing some crazy concatenation, then pulling in all apart to put in the HTML fields.
I can include some code, but it might be hard to follow as there are lots of variables being used.
The best I have gotten out using only table1 and table3:
Rob 1,2,3,4,5
Kevin
Amy 1,3,4
With the records that have not been entered not be accounted for, it makes it near impossible to turn the data string into a table. If I can get something showing for every position, even if it does not exist yet, I do know how to make it into the html table.
I hope this makes sense and someone can help me with this.
As you stated that you have at most 5 goals. The best possible option is to use following query.
SELECT t1.Name,t1.email
,CASE WHEN t2.Info IS NULL THEN * ELSE t2.Info END as Info
,CASE WHEN g1.Goal IS NULL THEN * ELSE g1.Goal END as Goal1
,CASE WHEN g2.Goal IS NULL THEN * ELSE g2.Goal END as Goal2
,CASE WHEN g3.Goal IS NULL THEN * ELSE g3.Goal END as Goal3
,CASE WHEN g4.Goal IS NULL THEN * ELSE g4.Goal END as Goal4
,CASE WHEN g5.Goal IS NULL THEN * ELSE g5.Goal END as Goal5
FROM Table1 as t1
LEFT JOIN Table2 as t2 ON t2.id = t1.Index
LEFT JOIN Table3 as g1 ON g1.id = t1.Index AND g1.Goal=1
LEFT JOIN Table3 as g2 ON g2.id = t1.Index AND g2.Goal=2
LEFT JOIN Table3 as g3 ON g3.id = t1.Index AND g3.Goal=3
LEFT JOIN Table3 as g4 ON g4.id = t1.Index AND g4.Goal=4
LEFT JOIN Table3 as g5 ON g5.id = t1.Index AND g5.Goal=5
You will want to JOIN each of the tables together, and GROUP BY the user.
One way of handling the goals would be to display it as one column, containing all goals.
This should help you get started:
SELECT name,
email,
info,
<LOGIC> as goals
FROM table1
JOIN table2 ON table2.user_id = table1.id
JOIN table3 ON table3.user_id = table1.id
GROUP BY name
The logic that you use for the goals column could be created with a mixture of CASE and CONCAT (if a goal is defined, concatenate it into a string, and display that string as the final value of goals).
[TABLE 1]
+---------+---------+------------------+
| post_id | user_id | description |
+---------+---------+------------------+
| 1 | 1 | Sample post 1 |
| 2 | 1 | Sample post 2 |
| 3 | 2 | Sample post 3 |
| 4 | 2 | Sample post 4 |
| 5 | 3 | Sample post 5 |
+---------+---------+------------------+
[TABLE 2]
+---------+---------+---------+
| id | user_id | post_id |
+---------+---------+---------+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
+---------+---------+---------+
When the USER_ID 1 in TABLE 1 already existed in TABLE 2 with its respected POST_ID, it should not be part of return select query. Instead, it would return POST_ID 2,3,4,5 in TABLE 1.
When the USER_ID 2 in TABLE 1 already existed in TABLE 2 with its respected POST_ID, the expected return select query would be POST_ID 1,3,4,5 in TABLE 1 as well as the other id's.
Thanks in advance guys! :)
Looks like an anti join pattern could achieve the specified result.
SELECT t.post_id
, t.user_id
, t.description
FROM `[Table 1]` t
LEFT
JOIN `[Table 2]` u
ON u.post_id = t.post_id
AND u.user_id = ?
WHERE u.post_id IS NULL
ORDER BY t.post_id
The ? is the placeholder character for specifying a userid.
This essentially says return all rows from Table 1 along with matching rows from Table 2, but (here's the trick) the WHERE clause says to exclude all rows that found a matching row in Table 2. Leaving only rows from Table 1 that don't have a match in Table 2.
The anti join takes a little bit of effort to get your brain wrapped around, but once you get it, it's an invaluable tool to keep handy in the SQL toolbelt.
There are other query patterns that will return an equivalent result, such as a NOT EXISTS (correlated subquery) or the more common NOT IN (subquery). (With the NOT IN, be careful that the subquery doesn't return any NULL values.)
EDIT
Removed the condition u.user_id = t.user_id from the join predicate. Looks like the user_id in [Table 1] is the "author" of the post. And has no relation to whether a user has "viewed" a post or not.
Base on your sample data, because USER_ID 1 in TABLE 1 already existed in TABLE 2 with its respected POST_ID, it should return POST_ID 2,3,4,5.
Query:
SELECT t1.* FROM table2 t2
RIGHT OUTER JOIN table1 t1
ON t2.user_id = t1.user_id AND t2.post_id = t1.post_id
WHERE t2.user_id IS NULL
Final Result:
post_id user_id description
2 1 Sample post 2
3 2 Sample post 3
4 2 Sample post 4
5 3 Sample post 5
Is this what you are looking for?
i have a little problem with MySql query. I have two tables:
Table name "users"
id, profilephoto, sex, name, lastname
Table name "friends"
id, idSender, idReceiver
idSender and idReceiver is value of id users who send friend request, and who get friend request.
Now i need get all users who is not friend with some login user (for example - User ID - 12)
I make this query:
SELECT DISTINCT users.id, users.profilephoto,users.sex,users.name,users.lastname FROM users INNER JOIN friends ON users.id=friends.idSender WHERE (friends.idSender!=12 OR friends.idReceiver!=12)
And I get wrong informations.
If someone have any idea, I will be thankful.
Simple data from table>
Table Users:
id | profilephoto | sex | name | lastname
1 | image1.jpg | 1 | John | Snow
2 | image2.jpg | 2 | Lisa | Test
3 | image3.jpg | 1 | Patric | Test
4 | image4.jpg | 2 | Elizabet | Test
Table friends:
id | idReceiver | idSender
1 | 1 | 2 // Lisa send friend request to John
2 | 2 | 3 // Patric send friend request to Lisa
For Lisa I want to display only Elizabet
For Elizabet I want to display Lisa, John and Patric
For John I need Patric and Elizabet
For Patric I need John and Elizabet
You need to make left join
SELECT * from users u
LEFT JOIN friends f ON u.id = f.idSender OR u.id = f.idReceiver
WHERE u.id = 12
AND f.idSender IS NULL
OR f.idReciever IS NULL
Hope it helps.
I think trying this query will select user has no friends
select u.*
from user u
left join friends f on f.idSender= u.id or f.idReceiver= u.id
where f.id is null
I've a following query to select data from a table (chat) in a chat system:
SELECT * FROM (SELECT * FROM chat WHERE id_chat = '$chat_id' ORDER BY id DESC LIMIT 10) S
WHERE id_chat = '$chat_id'
ORDER BY id ASC
LIMIT 10
In this table (chat), there is a user column where it is the user id that sent the message.
I would, from the id_from of the user who sent the message, get back data that user (users table).
Table chat:
id | id_chat | id_from | id_to | message | date
1 | 23 | 1 | 2 | hello! | 01-12-2016
Table users:
id | name | photo
1 | John | pic.png
2 | Nick | hey.jpg
What better way to do it using the above query? LEFT JOIN? INNER JOIN? And, how do?