Oracle SQL:从一个表中选择一个计数,从另一个表中使用子查询缩小选择范围
Posted
技术标签:
【中文标题】Oracle SQL:从一个表中选择一个计数,从另一个表中使用子查询缩小选择范围【英文标题】:Oracle SQL: select a count from one table, narrow the selection with subquery from another table 【发布时间】:2016-09-08 04:26:17 【问题描述】:目标:按角色或某些角色排除项返回在日期 X 登录的人数。
我过去以各种方式完成此操作,通常是选择我想要的,然后使用应用程序语言(php 等)循环遍历结果集,查询第二个表。我正在寻找一种更有效的,也许是纯 sql 的方式来做到这一点。
LoginTable
+--------------------+
| userName loginDate |
+--------------------+
| jason 08/15/16 |
| jason 09/01/16 |
| john 08/15/16 |
| john 09/04/16 |
| cindy 08/15/16 |
+--------------------+
RoleTable
+--------------------+
| userName role|
+--------------------+
| jason admin |
| jason student |
| jason employee |
| john employee |
| john admin |
| cindy student |
| cindy hr |
| cindy finance |
+--------------------+
有没有一种纯粹的 oracle SQL 方法可以做到这一点,而不需要进一步的后处理?
例如,一个问题可能是: 谁在 2016 年 8 月 15 日登录,谁拥有员工角色,而不是学生角色。
答案应该是约翰。
从登录表中选择用户名 其中 loginDate = 08/15/16 和 LoginTable.userName in(从 RoleTable 中选择用户名,其中角色 = 员工和角色 学生)
这个查询当然是行不通的。
是否有一种纯 sql 方法来执行此操作,或者我应该返回循环/后处理或临时表?
我正在寻找效率,因为这些表将有数百万行。
【问题讨论】:
编辑,试图把表格弄好。 您更改了问题,从而使我的答案不正确。你不应该那样做。 【参考方案1】:更新:
这是更新后问题的答案,与最初提出的问题有很大不同(q.v. 下面)
您可以对RoleTable
中的用户使用条件聚合来确定哪些用户具有employee
角色而不是student
角色。然后您可以进一步将其限制为登录08/15/16
的用户:
SELECT t1.userName
FROM RoleTable t1
INNER JOIN LoginTable t2
ON t1.userName = t2.userName
WHERE t1.loginDate = TO_DATE('08/15/16', 'DD/MM/YY')
GROUP BY t1.userName
HAVING SUM(CASE WHEN t1.role = 'employee' THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN t1.role = 'student' THEN 1 ELSE 0 END) = 0
注意:自从我第一次给出这个答案以来,这个问题发生了很大的变化。最初的问题是计算每个角色在特定日期登录的学生人数。
SELECT t1.role,
SUM(CASE WHEN t2.userName IS NOT NULL THEN 1 ELSE 0 END) AS peopleCount
FROM RoleTable t1
LEFT JOIN LoginTable t2
ON t1.userName = t2.userName
WHERE t1.loginDate = '08/15/16'
GROUP BY t1.role
【讨论】:
他想要具有指定角色的人名。 @sql_dummy 他在一小时前改变了他的问题。【参考方案2】:SELECT DISTINCT userName
FROM LoginTable
WHERE loginDate = TO_DATE('08/15/16', 'DD/MM/YY')
-- include
AND userName IN (SELECT userName FROM RoleTable WHERE role = 'employee')
-- exclude
AND userName NOT IN (SELECT userName FROM RoleTable WHERE role = 'student')
【讨论】:
以上是关于Oracle SQL:从一个表中选择一个计数,从另一个表中使用子查询缩小选择范围的主要内容,如果未能解决你的问题,请参考以下文章