PHP: SELECT ing 2 tables? - php

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

Related

How to fetch a emp first login and filter who's login time > 09:45:00 of every day of each emp

The table data I'm getting from database and I need to get only time which is greater than 9:45:00
Table Image link
So How to sort or filter the time which is less than 9:45:00 am
which is time less than 9:45 should be in hidden.
SELECT UserId,employees.EmployeeName as name, MIN(LogDate) as FirstLogin
FROM devicelogs_processed
LEFT JOIN employees ON employees.EmployeeCode = devicelogs_processed.UserId
WHERE '$empId'= UserId AND LogDate BETWEEN '2022-07-01' AND '2022-07-31'
GROUP BY UserId, YEAR(LogDate), MONTH(LogDate), DAY(LogDate)
ORDER BY `FirstLogin` DESC
use mysql function time(), extracts the time part from a given time/datetime expression, and add to your query TIME(LogDate) > '9:45:00'
SELECT UserId,employees.EmployeeName as name, MIN(LogDate) as FirstLogin
FROM devicelogs_processed
LEFT JOIN employees ON employees.EmployeeCode = devicelogs_processed.UserId
WHERE '$empId'= UserId AND LogDate BETWEEN '2022-07-01' AND '2022-07-31' and TIME(LogDate) > '9:45:00'
GROUP BY UserId, YEAR(LogDate), MONTH(LogDate), DAY(LogDate)
ORDER BY `FirstLogin` DESC

combine two select queries from the same mysql table

We have a table of users with column membership_end which is, as the name say - the date when users membership end. Now some users never purchase membership so that field is empty. For some users, that field is in the past (membership expired).
What I need is to sort the active members first (ordered by the membership_end date desc), then the rest of the users in some independent sorting order. Basically we need to show active members on top.
SELECT * FROM accounts where membership_end>=now()
order by membership_end desc
union
???
Should we use union or something else?
What would be a second query to avoid duplicates?
Thanks in advance
Ok, to clear things up a bit.
SELECT * FROM accounts where membership_end>=now()
order by membership_end desc
gives us 12 active members and this is fine. we then have this:
SELECT * FROM accounts where membership_end<now()
order by id desc
we simply need to combine these two in one query. that's all.
EDIT:
Actually i figured it out. It's quite simple.
SELECT id, membership_end
FROM accounts
ORDER BY membership_end >= NOW( ) DESC , id DESC
no unions. no complicated queries :-)
You can sort null values to be first, so you could avoid unions :
SELECT membership_end FROM accounts
where membership_end>=now() or membership_end is null
ORDER BY [membership_end] IS NULL DESC, [membership_end] DESC
If you do not want duplicates I would recommend to do this. I don't know what condition you want to use to filter members with null membership_end filed but if all I would do something like that:
SELECT membership_end FROM accounts where membership_end>=now() or membership_end is null order by membership_end desc
Descending ordering should put members with null membership_end in the end of list so you may want to add additional ordering.
Try something like this:
SELECT membership_end FROM table1 where membership_end>=now()
Union all
SELECT membership_end FROM table2 where membership_end>=now()
this will combine table1 and table2
The important bit is 1 field for table1 and 1 field for table2 only. It must be the same.
Two tricks here 1) associate ids with dates by creating a combined date + id field, historic and nulls have been given a seed date in the future to avoid overlaps with future dated members (you may wish to push this out) 2) allocate a srce number to the unioned statements.
/*
create table m (id int, enddte date);
truncate table m;
insert into m values
(1,null),(2,'2016-10-01'),(3,'2016-11-10'),(4,'2016-02-01'),(5,'2016-03-01'),(6,null);
*/
select * from
(
select 1 as srce,m.id,m.enddte ,
year(m.enddte) * 10000 + month(m.enddte) * 100 + m.id as uniqueid
from m
where m.enddte >= now()
) s
union
(
select 2,id,enddte,
year(cast('2050-01-01' as date)) * 10000 + month(cast('2050-01-01' as date)) * 100 + id
from m
where m.enddte < now() or m.enddte is null
)
order by srce,uniqueid desc
or you could do this without a union
select * from
(
select case
when enddte >= now() then 1
else 2
end as srce,
id, enddte,
case
when enddte >= now() then year(m.enddte) * 10000 + month(m.enddte) * 100 + m.id
else year(cast('2050-01-01' as date)) * 10000 + month(cast('2050-01-01' as date)) * 100 + id
end as uniqueid
from m
) s order by srce,uniqueid desc

select query from 2 tables with conditions

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)

show results of multiple mysql tables and sort

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.

PHP / MySQL Checking data between tables with long query

This is a more detailed question as my previous attempt wasn't clear enough. I'm new to MySQL and have no idea about the best way to do certain things. I'm building a voting application for images and am having trouble with some of the finer points of MySQL
My db
_votes
id
voter_id
image_id
_images
id
file_name
entrant_id
approved
_users
id
...
Basically I need to do the following:
tally up all votes that are approved
return the top 5 with the most votes
check if the user has voted on each of these 5 (return Boolean) from another table
I've tried variations of
SELECT i.id, i.file_name, i.total_votes
FROM _images i WHERE i.approved = 1
CASE WHEN (SELECT count(*) from _votes v WHERE v.image_id = i.id AND v.voter_id = ?) > 0 THEN '1' ELSE '0' END 'hasvoted'
ORDER BY i.total_votes DESC LIMIT ".($page*5).", 5
is that something I should try and do all in one query?
This query was working fine before I tried to add in the 'hasvoted' boolean:
SELECT id, file_name, total_votes FROM _images WHERE approved = 1 ORDER BY total_votes DESC LIMIT ".($page*5).", 5
At the moment I'm also storing the vote count in the _images table and I know this is wrong, but I have no idea about how to tally the votes by image_id and then order them.
Let me give this a shot to see if I understand your question:
SELECT i.*,(SELECT COUNT(*) FROM _votes WHERE i.id = image_id) AS total_votes, (SELECT count(*) from _votes where i.id = image_id and user_id = ?) as voted FROM _images AS i WHERE i.approved = 1

Categories