I am working on MySql and have two tables login_users and login_timestamps
Table login_users keeps a record of user_id, name and address whereas table login_timestamps keeps a record of user_id and timestamp, this table adds a new entry each time user logs in, so for example if the user_id '1' logs in 10 times a day, this table will have 10 entries for user_id '1' for today.
Now I need to fetch user profiles based on their last logged in time.
for example if there are 3 users, the MySql query should give me 3 records with their latest logged in time.
The query I am using is
SELECT * FROM login_users LEFT JOIN login_timestamps ON login_users.user_id = login_timestamps.user_id ORDER BY login_timestamps.timestamp DESC
but this gives me all the previous logged in entries rather than the recent one only.
Of course you will get all logged in entries while you didnt specify when or what day or something , hete you need a where clause.
try that:
SELECT * FROM login_users
LEFT JOIN login_timestamps ON login_users.user_id = login_timestamps.user_id
WHERE DATE(`timestamp`) = CURDATE()
ORDER BY login_timestamps.timestamp DESC
this will give you entries for curent day. of course you can specify any condition you want.
EDIT: from your comment.
try that
SELECT l.user_id, max(timestamp) as lasttime
FROM login_users l
LEFT JOIN login_timestamps lt ON l.user_id = lt.user_id
GROUP BY l.user_id
ORDER BY lasttime DESC
Related
I wish to fetch all users from "members" table but also check if the member_id from members table and user_id exist in"login" table and then see if column "activity" (current_timestamp) is less than 3600 seconds in login table than order those users on top rest users if don't exist in login table shows those users in bottom?
how cani query this please.
this is how i fetch users
$query = "SELECT * FROM members WHERE member_id != '".$_SESSION['member_id']."'";
but now how do i query the rest?
really thank you for your help.
Thanks
You need something like
SELECT members.*
FROM members
JOIN logins ON members.member_id = logins.member_id
WHERE logins.logged_in_at >= CURRENT_TIMESTAMP - INTERVAL 3600 SECOND
-- AND members.member_id != '$_SESSION['tfs_member_id']'
JOIN provides the presence in logins table, WHERE by logged_in_at filters "active" logins.
Use a LEFT JOIN with the logins table so you get members that aren't in the table. Then test whether the user is found in the logins table in the ORDER BY clause, and follow that by ordering by whether the last activity is recent.
SELECT m.*
FROM members AS m
LEFT JOIN logins as l ON m.member_id = l.member_id
ORDER BY l.member_id IS NULL,
l.activity > DATE_SUB(NOW(), INTERVAL 1 HOUR) DESC
I have a MYSQL query that I am having difficulties getting to do what I want.
I have a users table (userstbl) containing all my user records, and a listings table (listings) contains all listings posted by each user. I am trying to select the name and address of each user and provide a count of listings for each user which was listed between a certain date range, but only count adverts for unique category_id's which is working fine.
The issue is that I only want to count listings that have been published. I have another table which is identical to my listings table called "listings_log" and contains a record for every change made to every listing record. If one of the records in "listings_log" for the listing has a "listings_log.published=1" than the listing was published. Each record in the "listings_log" table has a "listing_id" which is the same as in the "listings" table.
This is the query I have now :
SELECT
userstbl.userid,
userstbl.fullname,
userstbl.fulladdress,
COUNT(DISTINCT(
CASE WHEN listings.ad_type = 1
AND DATE(listings.date_listed) BETWEEN '2018-01-01' AND '2018-04-01'
THEN listings.category_id
END )
) AS Listings_Count_2018,
DATE_FORMAT(userstbl.reg_date, "%d/%m/%Y") AS RegisteredDate
FROM
users
LEFT JOIN listings ON listings.userid = userstbl.user_id
GROUP BY userstbl.userid
This counts the number of unique listings records between the correct dates for each user.
But I somehow only need to count listings records, where there is a corresponding listings_log record for that listing with published set to "1". The "listings_log" table and "listings" table both have a common listing_id column, but the listings_log table can have multiple records for each listing showing every change to each listing.
So I want to also join on the listings_log.listing_id = listings.listing_id and at least one of the "listings_log" records for that "listing_id" has listings_log.published = "1".
As you did not provide sample tables and a minimal reproducible example, a lot of this is guesswork. I am assuming for each user you want the total number of listing records. I built up the SQL with subqueries that are meant to be read "from the inside out."
select u.userid, u.fullname, u.fulladdress, sq.count from usertbl u join (
select u.userid, sum(c.count) as count from usertbl u join (
select count(*) as count, l.userid, l.listing_id from listings l join (
select distinct listing_id from listings_log where listings_log.published = "1"
) ll on l.listing_id = ll.listing_id
and l.ad_type = 1
and date(l.date_listed) between '2018-01-01' and '2018-04-01'
group by l.userid, l.listing_id
) c on u.userid = c.userid
group by u.userid
) sq on u.userid = sq.userid
;
See DB Fiddle
A table users has three columns: id, name, pass.
Another table logins has user_id column, an isright boolean (tinyint) column which says whether the login was successful or not and a date column.
I need a simple left join to get the user's name and his password (1), the last login datetime (successful or not) (2) and the count of the logins for the specific user since his last successful login (3).
(1) and (2) I can achieve using
SELECT name, pass, MAX(date)
FROM users
LEFT JOIN logins ON logins.id = users.id
-- here either "GROUP BY users.id" or "WHERE users.id = 1234"
But (3) seems to be harder. I googled it and found many similar question but none of them was asking on exactly how to count rows after specific condition is true. (It's even more complicated - count the logins for that user, not everyone)
I don't even know how to do it in a separate query (I'd prefer having one query for the 3 things and I suppose I'd have to use a subquery, although I prefer joins).
SQL fiddle with the tables and some data: http://sqlfiddle.com/#!9/a932b
Any ideas?
The straight-forward way is to have two derived tables: One to get the last login date per user, the other to get the last successful login date per user. Then select from users, outer join the two derived tables and look whether the last login was successful and count the (failed) logins after the last successful login. (With another DBMS you would rather use analytic functions that MySQL lacks.)
select
users.name,
users.pass,
(
select max(isright)
from logins
where user_id = students.id and date = last_login.date
) as last_login_successful,
(
select count(*)
from logins
where user_id = students.id and date > last_successful_login.date
) as last_logins_failed
from users
left outer join
(
select user_id, max(date) as date
from logins
group by user_id
) last_login on last_login.user_id = users.id
left outer join
(
select user_id, max(date) as date
from logins
where isright = 1
group by user_id
) last_successful_login on last_successful_login.user_id = users.id;
This gives you four possibilities per user:
The user never tried to login. last_login_successful is null and last_logins_failed is meaningless.
The user's logins all failed. last_login_successful is 0 and last_logins_failed is meaningless.
The user's last login was successful. last_login_successful is 1 and last_logins_failed is meaningless.
The user logged in successfully once, but failed at least th last time they tried. last_login_successful is 0 and last_logins_failed is the number of failures after last successful login.
And here is a fiddle: http://sqlfiddle.com/#!9/57b7d/1.
EDIT: To also count failed logins when a user never logged in: If a user never logged in, their last_login.date is null. In last_logins_failed you want to count all records for which the last login occurred before OR never:
(
select count(*)
from logins
where user_id = students.id and (date > last_successful_login.date
or last_successful_login.date is null)
) as last_logins_failed
I guess you could do something like
select count(*)
from logins as l join users as u on l.user_id = u.id
where l.timestamp > (select max(timestamp)
from logins
where user_id = u.id and isright = 1)
Get the last timestamp of the login that was successful (subquery) for user
then get a count for all the logins where the timestamp is greater than that of the user, this automatically gives you only the unsuccessful logins because you took the last successful one as a reference timestamp/datetime
How about using a view which only has latest login detail with below query
select l.user_id, l.date, l.isright from logins l
where l.date >= (select max(l2.date) from logins l2
where l2.isright=1 and l2.user_id = l.user_id)
My sql's rusty. I need to select the 30 most recent messages (those with the 30 largest id's), and then use the sender_id to join with the users table id.
In English, I want the users who sent the last 30 messages.
Here my query (which doesn't run):
SELECT * FROM group_messages
WHERE group_id=52
ORDER BY id DESC
LIMIT 30
LEFT JOIN users
ON users.id=group_messages.sender_id
If there's a better approach to this kind of query, then by all means.
Note: The first part works in selecting the 30 most recent messages. The trouble came when I tried joining on the users table. (And I just realized even if this query did run, I would need to add GROUP BY users.id a user may have sent more than 1 of the 30 most recent messages.
The JOIN clause has to come before WHERE, ORDER BY, and LIMIT
SELECT DISTINCT id
FROM (
SELECT u.id
FROM group_messages AS g
INNER JOIN users AS u on u.id = g.sender_id
WHERE group_id = 52
ORDER BY id DESC
LIMIT 30) AS x
I put it in a subquery so I could then perform the DISTINCT selection. If you do that in the same query, it will get rid of the duplicates before selecting the most recent 30 rows, so you'll get the 30 most recent senders, not the senders of the 30 most recent messages.
I doubt you really need a LEFT JOIN instead of INNER JOIN. That would only be needed if a message could have a sender ID that isn't in users.
I am trying to return a list of users and their last login date. I need to get something that doesn't effect my outter order by statement because its dynamically populated by parameters the users chooses to sort the list. The other thing is the table that stores the login times requires 2 fields to link to the user table a user_id and a user_type.
table_admin
field: id, name
table_logs
field: id, user_id, user_type, login_date
*table_admin.id = table_logs.user_id
table_logs.user_type needs to be "admin"*
I need to pull all the admin users from table_admin with their last login date (it also needs to work if there is no record in the log table), the user_type in the log table would be "admin".
Thank you for your time.
SELECT SQL_CALC_FOUND_ROWS admins.*,ld2.ip,ld2.login_date as last_login
FROM admins
LEFT JOIN (
SELECT * FROM log_logins WHERE user_type = "admin" ORDER BY login_date DESC
) as ld2 ON (ld2.user_id = admins.id)
WHERE 1
GROUP BY user_id
ORDER BY admins.id DESC LIMIT 0,40
This is what I have so far but it doesn't grab results if they do not have an entry in the log table.
This is a join with an aggregation:
select a.name, 'admin' as userType, max(l.login_date) as lastLoginDate
from admin a left outer join
logs l
on a.id = l.id and
l.user_type = 'admin'
group by a.name