I have two tables in MySQL.
The logs table has columns: time, user_id, event_type
The users table has columns: email, id
Every time a user logs in to the system that generates the logs file, the event_type column value is logged with the value '/dashboard'.
The select statement here will show my every time they logged in...
SELECT users.email, logs.time
FROM users
LEFT JOIN logs ON users.id=logs.user_id
WHERE logs.event_type LIKE '/dashboard'
GROUP BY email, time;
...but I want to return the result set that shows the email address and timestamp for only the first time each user logged in.
You can use min for that:
SELECT users.email, min(logs.time)
FROM users
INNER JOIN logs ON users.id=logs.user_id
WHERE logs.event_type LIKE '/dashboard'
GROUP BY email;
Also no need for an outer join -- you are negating that in your where criteria. If you want to keep the outer join and return users that might not have matching records in the logs table, then move the criteria to the on:
SELECT users.email, min(logs.time)
FROM users
LEFT JOIN logs ON users.id=logs.user_id
AND logs.event_type LIKE '/dashboard'
GROUP BY email;
Related
In MySQL query, I wanted to query a list of recent login 1 user
information form each user type.
Table Information:
user table has columns: user_id, usertype_id, last_login_date
usertype table has columns: usertype_id, user_id
I have tried,
SELECT MAX(u.last_login_date), u.user_id FROM `user` u
JOIN usertype ut ON u.usertye_id = ut.usertype_id
GROUP BY ut.usertype_id;
But the above query returns 'last_login_date' irrespective of the user_id.
Any ideas will be appreciated.
select *
from (select u.last_login_date, u.user_id
from user u
order by u.last_login_date desc) x
group by last_login_date
With this solution you can avoid complicated subqueries that try to find the max() etc, and also the problems of returning multiple rows when there are more than one with the same maximum value
I want to get information from two tables users and results.
users table has
id, name, email, password columns etc.
and results table has
id, user_id, last_attempt_time etc.
The result table gets populated every time a user takes a quiz.
I want to display user_id,name and last_attempt_time but my query returns oldest time and i have no idea how to solve this problem.
SELECT u.id,u.email,u.name,u.joined,r.last_attempt_time FROM users u
LEFT JOIN results r
ON u.id=r.user_id
GROUP BY u.id
ORDER BY u.id ASC
Try:
SELECT u.id,u.email,u.name,u.joined,MAX(r.last_attempt_time) AS LastAttempt
FROM users u left join results r on u.id=r.quiz_id
GROUP BY u.id,u.email,u.name,u.joined
ORDER BY u.id ASC
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)
There are three tables:
events, users, and subscriptions
I am trying to query the database to extract some fields (see select statement).
Users table relationships:
Linked to subscriptions by user_id (not every user has a subscription_id)
Linked to events by user_id (not every user has an event)
The problem is that not every user has a corresponding entry in the subscriptions table. I would like to display all users that have an event - whether they have a subscription or not.
SELECT subscriptions.plan, subscriptions.created_at, subscriptions.expires_at, users.first_name, events.subdomain, events.heading
FROM users
LEFT OUTER JOIN subscriptions ON users.id = subscriptions.user_id
LEFT OUTER JOIN events ON users.id = events.user_id
UNION
SELECT subscriptions.plan, subscriptions.created_at, subscriptions.expires_at, users.first_name, events.subdomain, events.heading
FROM users
RIGHT OUTER JOIN subscriptions ON users.id = subscriptions.user_id
RIGHT OUTER JOIN events ON users.id = events.user_id
This query takes a while to run, but seems to yield double results for some events.
Currently it returns all users, and sometimes duplicate entries per event (which is not the case in the actual DB). Any help is appreciated!
I want to output users and their total number of wins and losses over requested date interval. When I run the query below within a date range that contains records in results table, everything works fine. However if a user does not have any records in results table for the requested date interval, then no user returned in the request at all. What I want is to return a user record anyway, even if the user does not have any records in results table for the requested date interval.
I believe the GROUP BY makes it behave that way, but I'm not sure how to configure the query to work the way I need it to.
SELECT
users.name,
users.division,
SUM(results.wins) as wins,
SUM(results.losses) as losses
FROM users LEFT JOIN results ON users.user_id = results.user_id
AND results.date BETWEEN {$startDate} AND {$endDate}
WHERE users.user_id = {$user_id} GROUP BY results.user_id;
The user is returned, just on a row where the id is NULL. You are grouping by the id in second table.
Instead, group by the first table field:
SELECT u.name, u.division,
SUM(r.wins) as wins, SUM(r.losses) as losses
FROM users u LEFT JOIN
results r
ON u.user_id = r.user_id AND r.date BETWEEN {$startDate} AND {$endDate}
WHERE u.user_id = {$user_id}
GROUP BY u.user_id;
---------^