Pull up login times in sql database - sql

I'm having a little trouble getting info from my database. I have a table containing two columns, one the player name, and the other the login time. I want to get a list of players and the number of times they logged in during a time period. However, users can login multiple times a day, but I want all logins within the same day to be counted as once.
To put this into context, I want a list of player name and the number of days in which the users have logged in during 2013-11-18 to 2013-11-24.
Is there a query that can return this result in one go?
I have tried using GROUP BY player_name but that just gives the number of times the player have logged in in total (large numbers because each player may login multiple times a day).
Any help would be appreciated.

SELECT player_name, COUNT(DISTINCT DATE(login_time))
FROM login_table
GROUP BY player_name;
Nail it, let me know if it doesnt work :)

I didn't try it, but this should do the job:
Select player_name, count(logged_in)
From (Select player_name, Date(login_date) As logged_in From ... Group By player_name, Date(login_date)) as tmp
Group By player_name
EDIT: Derived table must have an alias

Related

COUNT(*) function is returning multiple values

I am writing a specific sql query that needs to return the position of a particular entry, based on a grouped table.
Background info: I am coding a Golf Club Data Management system using Java and MS Access. In this system, the user is able to store their scores as a new entry into this table. Using this table, I have managed to extract a ranking of the top 3 Golf players, using all their recorded scores (I only used top 3 to preserve screen space).
Select TOP 3 Username, Sum(Points)
FROM Scores
GROUP By Username
ORDER BY Sum(Points) desc
This produces the required result. However, if the current user falls outside of the top 3, I want to be able to tell the user where they currently sit in the complete ranking of all the players. So, I tried to write a query that counts the number of players having a sum of points below the current user. Here is my query:
Select COUNT(*)
From Scores
GROUP BY Username
HAVING Sum(Points) < (Select Sum(Points)
FROM Scores
WHERE Username = 'Golfer210'
GROUP By Username)
This does not produce the expected number 2, but instead does this.
I have tried removing the GROUP BY function but that returns null. The COUNT DISTINCT Function refuses to work as well, and continuously returns a syntax error message, no matter how I word it.
Questions: Is there a way to count the number of entries while using a GROUP BY function? if not, is there an easier, more practical way to select the position of an entry from the grouped table? Or can this only be done in Java, after the ranking has been extracted from the database? I have not been able to find a solution anywhere
You need an additional level of aggregation:
SELECT COUNT(*)
FROM (SELECT COUNT(*)
FROM Scores
GROUP BY Username
HAVING Sum(Points) < (SELECT Sum(Points)
FROM Scores
WHERE Username = 'Golfer210'
)
) as s;
Note: You might want to check if your logic does what you expect when there are ties.

How can I select users based on whether or not there are multiple rows for that user?

I recently had an interview question that was worded something like this:
Select all users from the user table where the user works for multiple businesses and has a salary over 90000 at at least one of the businesses.
Where each row represented a user. Some users had multiple rows (for when they worked for multiple businesses) and each had a businessId.
I'm still pretty new to SQL, I do a lot of basic select and update statements when writing application code, but I'm not sure how to go about doing this. Should I be using count to find out if there are multiple rows for one user? I'm not sure how to structure it with the where clause to check the salary.
Group by the user (for instance the name). Then you can use the having clause to do aggregate operations in the group - meaning for every user
select username
from users
group by username
having count(distinct businessId) > 1
and max(salary) > 90000

Extract Both Counts AND Earliest Instance from my Dataset

Using Microsoft Sql 2000
I have a requirement to be able to email a monthly report that details a number of events.
(I have got the email bit sussed).
Amongst the data I need to email is a report on the number of certain courses people have attended. (so far so easy, couple of inner joins and a Count() and Im there.)
To add to that, some of the internal courses that we run have an expiry date which prompts a referesher course. I have been able to crudely get the data I need by using the sql code for part one and sticking the result set into a temp table, then by iterating over each row in that table, getting the user Id, querying the users course attendences, sorting it on date so that the earliest is at the top, and just taking the TOP 1 record.
This seems so inefficient, so is there any way I can ammend my current query so that I can also get the date of just the earliest course that the user attended?
i.e.
SELECT uName, COUNT(uId), [ not sure what would go in here] FROM UserDetails
INNER JOIN PassDates
ON PassDates.fkUser = uId)
GROUP BY uName, uId
where, for examples sake
UserDetails
uId
uName
and
PassDates
fkUser
CourseId
PassDate
Hope Ive explained this well enough for someone to help me.
To put an answer to the question..
SELECT uName, COUNT(uId), MIN(PassDate)
FROM UserDetails
INNER JOIN PassDates ON PassDates.fkUser = uId
GROUP BY uName, uId
You can turn it into a left join if you have users without any courses (yet)

SQL Query to return both distinct and total logins from a login table in sql2005

I have a table Logins { Id, AccessTime }, I'd like to write a query that returns 3 columns, Total Logins during a time period, Unique Logins for a time period, and the Id of the user.
I know I could do this with two passes and a join, is there a better way to do it in a single pass?
Thanks,
~Prescott
Edit: After considering this futher, if they they show up at all, then they are a unique login, thus I can just grab count(*), userId group by userid.
Sorry for the sillyness.
Poorly thought out before asking this question, essentially, if they have a record in the date period for Count(*), then their unique login is 1..

Compute Users average weight

I have two tables, Users and DoctorVisit
User
- UserID
- Name
DoctorsVisit
- UserID
- Weight
- Date
The doctorVisit table contains all the visits a particular user did to the doctor.
The user's weight is recorded per visit.
Query: Sum up all the Users weight, using the last doctor's visit's numbers. (then divide by number of users to get the average weight)
Note: some users may have not visited the doctor at all, while others may have visited many times.
I need the average weight of all users, but using the latest weight.
Update
I want the average weight across all users.
If I understand your question correctly, you should be able to get the average weight of all users based on their last visit from the following SQL statement. We use a subquery to get the last visit as a filter.
SELECT avg(uv.weight) FROM (SELECT weight FROM uservisit uv INNER JOIN
(SELECT userid, MAX(dateVisited) DateVisited FROM uservisit GROUP BY userid) us
ON us.UserID = uv.UserId and us.DateVisited = uv.DateVisited
I should point out that this does assume that there is a unique UserID that can be used to determine uniqueness. Also, if the DateVisited doesn't include a time but just a date, one patient who visits twice on the same day could skew the data.
This should get you the average weight per user if they have visited:
select user.name, temp.AvgWeight
from user left outer join (select userid, avg(weight)
from doctorsvisit
group by userid) temp
on user.userid = temp.userid
Write a query to select the most recent weight for each user (QueryA), and use that query as an inner select of a query to select the average (QueryB), e.g.,
SELECT AVG(weight) FROM (QueryA)
I think there's a mistake in your specs.
If you divide by all the users, your average will be too low. Each user that has no doctor visits will tend to drag the average towards zero. I don't believe that's what you want.
I'm too lazy to come up with an actual query, but it's going to be one of these things where you use a self join between the base table and a query with a group by that pulls out all the relevant Id, Visit Date pairs from the base table. The only thing you need the User table for is the Name.
We had a sample of the same problem in here a couple of weeks ago, I think. By the "same problem", I mean the problem where we want an attribute of the representative of a group, but where the attribute we want isn't included in the group by clause.
I think this will work, though I could be wrong:
Use an inner select to make sure you have the most recent visit, then use AVG. Your User table in this example is superfluous: since you have no weight data there and you don't care about user names, it doesn't do you any good to examine it.
SELECT AVG(dv.Weight)
FROM DoctorsVisit dv
WHERE dv.Date = (
SELECT MAX(Date)
FROM DoctorsVisit innerdv
WHERE innerdv.UserID = dv.UserID
)
If you're using SQL Server 2005 you don't need the sub query on the GROUP BY.
You can use the new ROW_NUMBER and PARTION BY functionality.
SELECT AVG(a.weight) FROM
(select
ROW_NUMBER() OVER(PARTITION BY dv.UserId ORDER BY Date desc) as ID,
dv.weight
from
DoctorsVisit dv) a
WHERE a.Id = 1
As someone else has mentioned though, this is the average weight across all the users who have VISITED the doctor. If you want the average weight across ALL of the users then anyone not visiting the doctor will give a misleading average.
Here's my stab at the solution:
select
avg(a.Weight) as AverageWeight
from
DoctorsVisit as a
innner join
(select
UserID,
max (Date) as LatestDate
from
DoctorsVisit
group by
UserID) as b
on a.UserID = b.UserID and a.Date = b.LatestDate;
Note that the User table isn't used at all.
This average omits entirely users who have no doctors visits at all, or whose weight is recorded as NULL in their latest doctors visit. This average is skewed if any users have more than one visit on the same date, and if the latest date is one of those date where the user got wighed more than once.