在SQL查询中包含一对多关系的计数

时间:2012-05-23 14:37:53

标签: sql

我有以下表格:

users
+----------+----------+----------+
| id       | name     | dob      |
+----------+----------+----------+

authentications
+----------+----------+----------+ 
| id       | user_id  | provider |
+----------+----------+----------+

用户,有许多身份验证。 user_id表中的authenticationsusers表的外键。

我试图补充以下输出:

+---------------+---------------+---------------+---------------+ 
|    user.id    |   user.name   |   user.dob    |       C       |
+---------------+---------------+---------------+---------------+

此处,C是提供者为“facebook”的用户身份验证的计数。如果不是计数,我可以得到一个布尔值,即如果存在认证则为true,否则为false,这将更好。

我无法想象如何构建查询。任何指针都会非常感激。

4 个答案:

答案 0 :(得分:2)

使用您在用户和身份验证之间的JOIN创建查询,并首先在User Id字段中添加GROUP BY。您的分组将需要包含您希望在结果中列出的后续字段,尽管它们不会更改结果的效果:

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

答案 1 :(得分:0)

C是计数,如果有facebook提供者,B将返回1,否则返回0(布尔值)。更新为使用LEFT OUTER JOIN以便包含所有用户。

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

答案 2 :(得分:0)

1)这将返回每个用户的FB类型授权的实际计数:

`

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)这将为每个用户返回true或false标志,具体取决于他们的授权类型:

`

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

`

在较小的数据集上使用连接:更快的响应。 最后,我相信这是一个:

`

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

`

答案 3 :(得分:-1)

早期的答案有效,但速度极慢。该查询过去需要15-20分钟才能运行。这个由朋友建议运行得快得多(对于同一个数据集约为4s)。

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;