Reputation: 10146
I have the following tables:
users
+----------+----------+----------+
| id | name | dob |
+----------+----------+----------+
authentications
+----------+----------+----------+
| id | user_id | provider |
+----------+----------+----------+
A user, has-many authentications. user_id
in the authentications
table is a foreign key to the users
table.
Im trying to comple the following output:
+---------------+---------------+---------------+---------------+
| user.id | user.name | user.dob | C |
+---------------+---------------+---------------+---------------+
Here, C is, the count of the users authentications where provider is 'facebook'. If instead of the count, I could get a boolean value, ie true if authentications are present, false if not, that would be even better.
I cant figure how to go about constructing the query. Any pointers would be much appreciated.
Upvotes: 0
Views: 2232
Reputation: 16
1) This will return the actual count of Authorization of type FB for every user :
`
Select Name UserName, ID UserID, COUNT(FBAuth) FBAuthCount
from Users LEFT JOIN
(Select UserID, COUNT(AuthType) FBAuth from Auth
Where AuthType = 'FB'
Group by USERID) Auths on (Users.ID = Auths.UserId)
Group by ID, Name
`
2) This will return the flag true or false for every user depending on thier authorization type:
`
Select Name UserName, ID UserID,
CASE WHEN COUNT(FBAuth) > 0 THEN 'TRUE' ELSE 'FALSE' END FBAuthFLAG
from Users LEFT JOIN
(Select UserID, COUNT(AuthType) FBAuth from Auth
Where AuthType = 'FB'
Group by USERID) Auths on (Users.ID = Auths.UserId)
Group by ID, Name
`
Using a join on smaller dataset: faster response. Finally, I believe this is the one:
`
SELECT users.id,
users.email,
users.name,
users.sid,
users.created_at,
( CASE
WHEN fb_auth > 0
THEN 'true'
ELSE 'false'
END ) AS facebook
FROM users
LEFT JOIN (SELECT authentications.user_id,
Count(authentications.provider) fb_auth
FROM authentications
WHERE provider = 'facebook'
GROUP BY user_id) auths
ON ( users.id = auths.user_id )
GROUP BY users.id,
users.email,
users.name,
users.sid,
users.created_at
`
Upvotes: 0
Reputation: 368
Create your query with your JOIN between users and authentications, and add in a GROUP BY on the User Id field first. Your group by will need to contain subsequent fields that you wish to list in your results although they won't change the effect of the results:
SELECT u.id, u.name, u.dob, COUNT(a.user_id) as authCount
FROM users u
LEFT JOIN authentications a on u.id = a.user_id
WHERE a.provider = 'facebook'
GROUP BY u.id, u.name, u.dob
Upvotes: 2
Reputation: 10146
The earlier answers worked, but were extremely slow. The query used to take 15-20 minutes, to run. This one, suggested by a friend runs much faster (~4s for the same dataset).
SELECT users.id,
users.email,
users.name,
users.sid,
users.created_at,
( CASE
WHEN fb_auth > 0
THEN 'true'
ELSE 'false'
END ) AS facebook
FROM users
LEFT JOIN (SELECT authentications.user_id,
Count(authentications.provider) fb_auth
FROM authentications
WHERE provider = 'facebook'
GROUP BY user_id) auths
ON ( users.id = auths.user_id )
GROUP BY users.id,
users.email,
users.name,
users.sid,
users.created_at;
Upvotes: -1
Reputation: 5244
C is the count, B will return 1 if there is a facebook provider and 0 if not (boolean). Updated to use LEFT OUTER JOIN so that all users are included.
SELECT
users.id,
users.name,
users.DOB,
SUM(CASE WHEN authentications.provider = 'facebook' then 1 else 0 end) as C,
MAX(CASE WHEN authentications.provider = 'facebook' then 1 else 0 end) as B
FROM users
LEFT OUTER JOIN authentications
ON users.id = authentications.user_id
GROUP BY users.id, users.name, users.DOB
Upvotes: 0