postgresql database - sql

i wanna to make a query that select users that have same username and same hour of creation date by using postgresql database

Something like this should do the trick. This will return any user/hour pair along with the count (untested):
select users.username, datepart('hour', users.created_at), count(*) from users
inner join users u2
on users.username = u2.username
and datepart('hour', users.created_at) = datepart('hour', u2.created_at)
group by users.username, datepart('hour', users.created_at) having count(*) > 1

select u.*
from users u
join (
select username, date_trunc('hour', creation_timestamp)
from users
group by 1, 2
having count(*) > 1
) as x on u.username = x.username
order by u.username;
Should work nicely.

Related

Join Equivalent For User Session Subquery

I have a user table with id column and request table with user_id and session_id columns.
I want to get the number of sessions each user has.
Here is the query I wrote using a subquery:
select user.id,
(
select count(distinct session_id)
from request
where request.user_id = user.id
) as session_count
from user
What would be the join equivalent of this?
What about this?
select u.id, count(distinct r.session_id)
from user u
join request r on r.user_id = u.id
group by u.id
You can use GROUP BY without need a subquery such as
SELECT u.id, COUNT(DISTINCT r.session_id)
FROM user u
JOIN request r
ON u.id = r.user_id
GROUP BY u.id

SQL: Comparing MAX Dates from Two different Tables

I have 3 Tables
User
Attendence
Payment
Now I like to get
GroupID, UserName, MAX(PaymetDate), MAX(AttendenceDate)
Where MAX(PaymetDate) IS LESS THAN MAX(AttendenceDate)
This what I have Tried
SELECT MAX(PaymetDate) AS Paied_Upto
FROM Payment
Group by GroupID
SELECT MAX(AttendenceDate) AS Last_ AttendenceDate
FROM Attendence FULL OUTER JOIN Users ON Attendence.Username = Users.Username
Group by Users.GroupID
But how do get them to work together?
Thank
Try this:
SELECT u.GroupID, u.UserName, py.LastPaymentDate, at.LastAttendenceDate
FROM User AS u,
(SELECT Username, Max(AttendenceDate) AS LastAttendenceDate FROM Attendence GROUP BY Username) AS at,
(SELECT GroupID, Max(PaymetDate) AS LastPaymentDate FROM Payment GROUP BY GroupID) AS py
WHERE u.UserName=at.Username
AND u.GroupID=py.GroupID
AND py.LastPaymentDate < at.LastAttendenceDate;
try this
select p.GroupID, u.UserName, MAX(p.PaymetDate), MAX(a.AttendenceDate)
from dbo.Users u
inner join dbo.Attandence a
ON u.UserName = a.UserName
Inner join dbo.Payment p
ON u.groupID = p.GroupID
GROUP BY p.GroupID, u.UserName
Having MAX(p.PaymentDate) < MAX(a.attendenceDate)
I think this does what you need (SqlFiddle link):
select UserName, GroupID, MaxAttendanceDate, MaxPaymentDate
from (
select
u.UserName,
u.GroupID,
(select max(AttendanceDate)
from Attendance a
where a.UserName = u.UserName) as MaxAttendanceDate,
(select max(PaymentDate)
from Payment p
where p.GroupID = u.GroupId) as MaxPaymentDate
from [User] u
) x
where MaxAttendanceDate > MaxPaymentDate

Writing a Mathematical Formula in SQL?

I have these tables: users, comments, ratings, and items
I would like to know if it is possible to write SQL query that basically does this:
user_id is in each table. I'd like a SQL query to count each occurrence in each table (except users of course). BUT, I want some tables to carry more weight than the others. Then I want to tally up a "score".
Here is an example:
user_id 5 occurs...
2 times in items;
5 times in comments;
11 times in ratings.
I want a formula/point system that totals something like this:
items 2 x 5 = 10;
comments 5 x 1 = 5;
ratings 11 x .5 = 5.5
TOTAL 21.5
This is what I have so far.....
SELECT u.users
COUNT(*) r.user_id
COUNT(*) c.user_id
COUNT(*) i.user_id
FROM users as u
JOIN COMMENTS as c
ON u.user_id = c_user_id
JOIN RATINGS as r
ON r.user_id = u.user_id
JOIN ITEMS as i
i.user_id = u.user_id
WHERE
????
GROUP BY u.user_id
ORDER by total DESC
I am not sure how to do the mathematical formula portion (if possible). Or how to tally up a total.
Final Code based on John Woo's Answer!
$sql = mysql_query("
SELECT u.username,
(a.totalCount * 5) +
(b.totalCount) +
(c.totalCount * .2) totalScore
FROM users u
LEFT JOIN
(
SELECT user_id, COUNT(user_id) totalCount
FROM items
GROUP BY user_id
) a ON a.user_id= u.user_id
LEFT JOIN
(
SELECT user_id, COUNT(user_id) totalCount
FROM comments
GROUP BY user_id
) b ON b.user_id= u.user_id
LEFT JOIN
(
SELECT user_id, COUNT(user_id) totalCount
FROM ratings
GROUP BY user_id
) c ON c.user_id = u.user_id
ORDER BY totalScore DESC LIMIT 10;");
Maybe this can help you,
SELECT u.user_ID,
(a.totalCount * 5) +
(b.totalCount) +
(c.totalCount * .2) totalScore
FROM users u LEFT JOIN
(
SELECT user_ID, COUNT(user_ID) totalCount
FROM items
GROUP BY user_ID
) a ON a.user_ID = u.user_ID
LEFT JOIN
(
SELECT user_ID, COUNT(user_ID) totalCount
FROM comments
GROUP BY user_ID
) b ON b.user_ID = u.user_ID
LEFT JOIN
(
SELECT user_ID, COUNT(user_ID) totalCount
FROM ratings
GROUP BY user_ID
) c ON c.user_ID = u.user_ID
ORDER BY totalScore DESC
but based on yur query above,thismay also work
SELECT u.users
(COUNT(*) * .5) +
COUNT(*) +
(COUNT(*) * 2) totalcore
FROM users as u
LEFT JOIN COMMENTS as c
ON u.user_id = c_user_id
LEFT JOIN RATINGS as r
ON r.user_id = u.user_id
LEFT JOIN ITEMS as i
ON i.user_id = u.user_id
GROUP BY u.user_id
ORDER by totalcore DESC
The only difference is by using LEFT JOIN. You will not use INNER JOIN in this situation because there are chances that user_id is not guaranteed to exists on every table.
Hope this makes sense
Here's an alternative approach:
SELECT
u.user_id,
SUM(s.weight) AS totalScore
FROM users u
LEFT JOIN (
SELECT user_id, 5.0 AS weight
FROM items
UNION ALL
SELECT user_id, 1.0
FROM comments
UNION ALL
SELECT user_id, 0.5
FROM ratings
) s
ON u.user_id = s.user_id
GROUP BY
u.user_id
I.e. for every occurrence of every user in every table, a row with a specific weight is produced. The UNIONed set of weights is then joined to the users table for subsequent grouping and aggregating.

MySQL: Find duplicate users WHERE item count < 1

Trying to find duplicate users by email, who have an item count less than 0. I've got the duplicate users working (though it returns the full list of users sorted, instead of a subset):
select users.id, email, count(email) as count
from users
group by users.email
order by count desc
I'm trying to join on Items where count(items.id) < 1, but that doesn't seem to work.
select users.id, email, count(email) as count
from users
join items on items.user_id = users.id
having count(items.id) < 1
group by users.email
order by count desc
I also tried an IN query, but can't seem to get the syntax right.
Easy way to do this? Thanks!
UPDATE:
This query did the trick:
select DISTINCT(u1.id), u1.email
from users u1
inner join users u2
on 1=1
and u1.email = u2.email
and u1.id != u2.id
where not exists (select * from items i where i.user_id = u1.id)
order by u1.id
Duplicated users:
select
email,
count(*) as count,
min(id) first_user_with_this_email_id
from users
group by email
having count(*) > 1
For second one, try this:
select
users.email,
count(*) as count
from users
left join items
on (items.user_id = users.id)
where items.id is null --there are no related items
group by users.email
having count(*) > 1 --there are at least two users
Another version of second:
select
u.email,
count(*) as count
from users u
where not exists (select * from items i where i.user_id = u.id)
group by u.email
having count(*) > 1 --there are at least two users
Make sure you have index on user_id in items table.
try using WHERE instead of "having".
May be this link helps: http://www.devx.com/DevX/Tip/21295
Modified query would be :
select users.id, email, count(email) as count
from users
join items on items.user_id = users.id
where count(items.id) < 1
group by users.email
order by count desc
[ did not run and check the query, just a correction ]

How to select all users who made more than 10 submissions

I have a submission table that is very simple: userId, submissionGuid
I want to select the username (simple inner join to get it) of all the users who have more than 10 submissions in the table.
I would do this with embedded queries and a group by to count submissions... but is there a better way of doing it (without embedded queries)?
Thanks!
This is the simplest way, I believe:
select userId
from submission
group by userId
having count(submissionGuid) > 10
select userId, count(*)
from submissions
having count(*) > 10
group by userId
SELECT
username
FROM
usertable
JOIN submissions
ON usertable.userid = submissions.userid
GROUP BY
usertable.username
HAVING
Count(*) > 1
*Assuming that your "Users" table is call usertable and that it has a column called "UserName"
I think the correct query is this (SQL Server):
SELECT s.userId, u.userName
FROM submission s INNER JOIN users u on u.userId = s.userId
GROUP BY s.userId, u.username
HAVING COUNT(submissionGuid) > 10
If you don't have the HAVING clause:
SELECT u.userId, u.userName
FROM users u INNER JOIN (
SELECT userId, COUNT(submissionGuid) AS cnt
FROM submission
GROUP BY userId ) sc ON sc.userId = u.userId
WHERE sc.cnt > 10
select userid, count(submissionGUID) as submitCount
from Submissions
group by userid, submitCount
having submitCount > 10