I have page where people can post comments and page where people can click "follow" on other people profiles (same as LIKE on Facebook)
I would like to have SELECT query that will post all the comments I have, but will order them with the follow way:
First, print the 2 newest comments (they must been posted this week) of the lastest people you click FOLLOW.
Second, post the rest of the posted, order them by create-date
(I'm using linux time)
Can you help me with the SQL query?
This is my current SELECT query. it pull all comment by create-date:
SELECT
id, userID, text, createDate
FROM `comments` AS comment
WHERE (comment.refID = 0)
AND (comment.pageName = 'yard')
AND 1=1
ORDER BY comment.createDate DESC LIMIT 0, 20
"followers" table looks like this:
userID ownerID createDate
1 2 1439019657
1 4 1438940399
(user 1 is following after user 2 and 4)
"comments" table looks loke this:
id userID pageName refID text createDate
220 1 yard 0 text1 1438030967
227 1 yard 0 text2 1438031704
228 1 yard 0 text3 1438031704
(userID - which user publish the comment. refID - always "0". pageName - always "yard")
So is this case, if I'm user number 1, than I would like to see the newest 2 comments of users 2 and 4 (only if they where made in the last week) and than to see all the rest of the comments (of all users) order by date (without , of course, the once that I already saw)
You are going to have to split this up into 2 queries.. ..and I am guessing at some of the table relationships here..
// get the last 2 comments from followed users..
SELECT *
FROM comments
WHERE userID IN (
SELECT ownerID
FROM followers
WHERE userID = ?
) ORDER BY createDate DESC
LIMIT 2
// then get the rest, removing already returned comments
SELECT *
FROM comments
WHERE id NOT IN (
-- either put the above query in here
-- or buuild an array of the 'id's when outputting the results above
-- and use that in here to prevent them being returned again
) ORDER BY createDate DESC
(select com.userID,com.page,com.text
from followers as fol
JOIN comments as com
ON fol.ownerId=com.userId
where
(
from_unixtime(com.createDate) BETWEEN
(
UNIX_TIMESTAMP(DATE_ADD(CURDATE(),INTERVAL -14 DAY) AND UNIX_TIMESTAMP(NOW())
)
Order BY com.createDate desc
)
Union
(select com.userID,com.page,com.text
from comments as com
where com.id NOT In
(select com.id
from followers as fol
JOIN comments as com
ON fol.userId=com.userId
where
(
from_unixtime(com.createDate) BETWEEN
(
UNIX_TIMESTAMP(DATE_ADD(CURDATE(),INTERVAL -14 DAY) AND UNIX_TIMESTAMP(NOW())
)
)
Order BY com.createDate desc
)
Explanation:
There are two queries merged in one using union.
Select statement will give all the data follower comments.
this is accomplished using Join.
Select statement to get all the other comments then the comments of the above 1st query.
the only thing that is not clear is how you are deciding whether the
comments is been read by the user (Insufficient information)
Related
I have page where people can post comments and page where people can click "follow" on other people profiles (same as LIKE on Facebook)
I would like to have SELECT query that will post all the comments I have, but will order them with the follow way:
first, print the 2 newest comments (they must been posted this week) of the lastest people you click FOLLOW.
second, post the rest of the posted, order them by create-date
(I'm using linux time)
Can you help me with the SQL query?
this is my current SELECT query. it pull all comment by create-date:
SELECT id, userID, text, createDate FROM `comments` AS comment WHERE (comment.refID = 0) AND (comment.pageName = 'yard') AND 1=1 ORDER BY comment.createDate DESC LIMIT 0, 20
"followers" table looks like this:
userID ownerID createDate
1 2 1439019657
1 4 1438940399
"comments" table looks loke this:
id userID pageName refID text createDate
220 1 yard 0 text1 1438030967
227 1 yard 0 text2 1438031704
228 1 yard 0 text3 1438031704
I might've messed up followers' relations. Example data looks incoplete for full context. It shows userID=1 comments for sure, but either no one who follows userID=1 or both 3 and 4 follow him. No idea what refID is doing in comments table. Query shows only a concept anyway - you'll figure out details.
SELECT un.* FROM ((
SELECT 1 as priority, comment.id, comment.userID, comment.text, comment.createDate
FROM `comments` as comment
INNER JOIN `followers` as follower ON follower.userID = comment.userID
WHERE comment.refID = 0
AND comment.pageName = 'yard'
AND ...
ORDER BY follower.createDate DESC LIMIT 2
) UNION DISTINCT (
SELECT 2 as priority, id, userID, text, createDate
FROM `comments` as comment
WHERE comment.refID = 0
AND comment.pageName = 'yard'
)) as un ORDER BY un.priority, un.createDate DESC LIMIT 20
I have 4 tables:
Table 1: Users
id
username
Table 2: Acts
act_id
act
user_id
act_score
act_date
Table 3: Votes
vote_id
act_id
user_voter_id
score_given
date_voted
Table 4: Comments
comment_id
comment
commenter_id
act_commented
date_commented
I want to show the contents of Acts Votes and Comments, based on User ID, combined in a list sorted in date order. Similar idea to Facebook's NewsFeed.
Sample output:
05-02-2014 10:00 Comment: "That's funny"
04-02-2014 12:30 Act Posted: "This is what I did"
04-02-2014 11:00 Comment: "Rubbish"
03-02-2014 21:00 Comment: "Looks green to me"
02-02-2014 09:00 Voted: +10 "Beat my personal best" by Cindy
01-02-2014 14:25 Act Posted: "Finally finished this darn website!"
I have tried to go down the create VIEW route to add all the required info to a table but
it was the wrong path. Now I'm not sure what to do!
Use UNION to combine separate queries. For example, to get the 10 most recent events across the three tables:
(
-- my acts
SELECT a.act_date timestamp,
'Act Posted' type,
a.act description,
u.username
FROM Acts a
JOIN Users u ON u.id = a.user_id
WHERE a.user_id = ?
ORDER BY a.act_date DESC
LIMIT 10
) UNION ALL (
-- votes on my acts
SELECT v.date_voted,
CONCAT('Voted ', v.score_given),
a.act,
u.username
FROM Votes v
JOIN Acts a USING (act_id)
JOIN Users u ON u.id = v.user_voter_id
WHERE a.user_id = ?
ORDER BY v.date_voted DESC
LIMIT 10
) UNION ALL (
-- comments on my acts
SELECT c.date_commented,
'Comment',
c.comment,
u.username
FROM Comments c
JOIN Acts a ON a.act_id = c.act_commented
JOIN Users u ON u.id = c.commenter_id
WHERE a.user_id = ?
ORDER BY c.date_commented DESC
LIMIT 10
)
ORDER BY timestamp DESC
LIMIT 10
first of all make id as a foreign key and use it in rest of the 3 tables while inserting data into those 3 tables.
like for Acts table,table structure should be like below.
Table 2: Acts
id //this is user id which is stored in the session while login.
act_id
act
user_id
act_score
act_date
The another thing to do is manage session for each and every user while he/she logged in.
Store user_id in the session for the further use like below.
session_start();
$_SESSION['user_id']=$_POST['ID'];
Then,fire select query for the particular table.I give you example of select query.
$sql="select * from Acts where id='".$_SESSION['id']."' ORDER BY act_date DESC";
$query=mysql_query($sql) or die("query failed");
Now, you will get result of Acts of particular user order by date.Then print it wherever you want.
Okay so I have a table that has the following
KEY username password score
The above columns are not in any specific order.
I want to send my Database a username and have it send me back what rank that user name is based on its score. So for example if I had 10 people in there and the 3rd person in has the highest score. When I pass the 3rd persons username in I want it to send back 1.
Is this possible?
I have been trying things like this
$result = mysql_query("SELECT * FROM tablename where username='$username' ORDER BY score DESC");
but it doesnt seem to give me the row number
This will handle ranks that have the same score.
SELECT d.*, c.ranks
FROM
(
SELECT Score, #rank:=#rank+1 Ranks
FROM
(
SELECT DISTINCT Score
FROM tableName a
ORDER BY score DESC
) t, (SELECT #rank:= 0) r
) c
INNER JOIN tableName d
ON c.score = d.score
// WHERE d.username = 'Helen'
SQLFiddle Demo (Ranking with duplicates)
SQLFiddle Demo (with filtering)
for example
KEY username password score Ranks
1 Anna 123 5 3
2 Bobby 345 6 2
3 Helen 678 6 2
4 Jon 567 2 4
5 Arthur ddd 8 1
for better performance, add an INDEX on column Score,
ALTER TABLE tableName ADD INDEX (Score)
SELECT
(SELECT COUNT(*)+1 FROM tablename WHERE score > t.score) as rank,
*
FROM
tablename t
where
username='$username'
The ORDER BY in your query is useless since you're only returning one row.
I want to select the newest posts from users, I am looking for the most efficient way to do this.
Currently this selects the first post, not the last:
$query = mysql_query("
SELECT *
FROM posts
WHERE toID=fromID
GROUP BY fromID
ORDER BY date DESC LIMIT 3");
Table Structure:
Table: posts
id ToID FromID Post State Date
1 1 1 Hey 0 1325993600
2 1 6 okay yeah 0 1325993615
3 1 2 again 0 1325994600
4 6 6 yeah2 0 1325995615
so from this above example it would return id: 1 and 4.
toID=fromID is just to get the post that is a status message, meaning the user posted something on their own page, not someone elses.
I want to get the most recent status from the last 3 users that have updated their status.
The ID thing would still work theoretically, provided that the ID's never change...
I would recommend using a timestamp field in the table structure called "date" and use the "CURRENT_TIMESTAMP" as default value, this will auto-populate the date/time on the record upon insert...
Order by this field DESC, limit x
Also, I have experienced many cases of the wrong data appearing thanks to grouping... Make sure your data is correct before ORDER BY and LIMIT is applied
For getting posts from user1 to user1 there's no need to group by:
SELECT * FROM posts
WHERE toID=fromID
ORDER BY date DESC LIMIT 3
For getting posts from * to user1:
SELECT * FROM posts
WHERE toID="USER1_ID"
ORDER BY date DESC LIMIT 3
For getting posts from * to user1, only unique users:
SELECT * FROM posts
WHERE toID="USER1_ID"
GROUP BY FromID
ORDER BY date DESC LIMIT 3
Somtimes you will run into the problem where GROUPED records are not ordered by ORDER BY, because the ORDER BY is applied to the result AFTER the grouping is applied... To achieve a workaround:
SELECT * FROM (
SELECT * FROM posts
WHERE toID="USER1_ID"
ORDER BY date DESC
) as `derived` GROUP BY FromID LIMIT 3
To Get the last 3 users who have most recently sent themselves a post:
SELECT * FROM (
SELECT * FROM posts
WHERE toID=fromID
ORDER BY date DESC
) as `derived` GROUP BY FromID LIMIT 3
try this query.
$query = mysql_query("SELECT * FROM posts WHERE toID=fromID GROUP BY id ORDER BY date DESC LIMIT 3");
I have a activities page and a statusmessages page for each user.
In activities it contains what the users have done, such as being friends with someone, commented on pictures and so.
users_activities
id | uID | msg | date
In users_statusmessages, I got the statusmessages, the user creates.
users_statuses
id | uID | message | date
uID is the userĀ“s id.
Now i would like to select both of them and while{} them in one. Where they get sorted by date desc ( as the date in both tables is UNIX timestamp).
So something like WHERE uID = '$userID' ORDER BY date DESC
So example of how i wish it to look:
User: Today is a good day (message) (date: 1284915827) (users_statuses)
User have added as Jack as friend (msg) (date: 1284915811) (users_activities)
User: I have a hard day today (message) (date: 1284915801) (users_statuses)
User have commented on Jacks picture (msg) (date: 1284915776) (users_activities)
How should i do this the right way?
You need to use the UNION operator:
SELECT ua.msg,
ua.date,
'activity' AS is_table
FROM USERS_ACTIVITIES ua
WHERE ua.uid = '{$userID}'
UNION ALL
SELECT us.message,
us.date,
'status'
FROM USERS_STATUSES us
WHERE us.uid = '{$userID}'
ORDER BY `date`
UNION
UNION removes duplicates. UNION ALL does not remove duplicates, and is faster for it.
But the data types at each position in the SELECT must match. In the query provided, you can see that the date column is referenced in the second position. You'd get an error if the column order were reversed between the first and second query.
The ORDER BY is applied to the result of the UNION'd query in standard SQL. In MySQL, that includes the LIMIT clause. But MySQL also supports putting brackets around the UNION'd queries so you can use ORDER BY & LIMIT before the queries are UNION'd.
You're going to want to use a union
http://dev.mysql.com/doc/refman/5.0/en/union.html
This is untested...
(SELECT uID, msg as message, date from users_activities)
UNION
(SELECT uId, message, date from users_statuses) order by date desc limit 20
There are a lot more examples on that page
Something like this would do
SELECT act.*,status.* FROM users_activities act, users_statuses status WHERE act.id = status.id AND status.id = '$UID' ORDER BY status.date,act.date DESC LIMIT 30
Spaced out for visual purposes:
SELECT
act.*,status.*
FROM
users_activities act,
users_statuses status
WHERE
act.id = status.id
AND
status.id = '$UID'
ORDER BY
status.date,act.date DESC
LIMIT
30