我有一个由用户,练习和分数组成的表格。下面可以看到表的结构和一些示例数据(只是为了给你一个想法)。
|UserID | ExerciseID | Score |
------------------------------
|1 | 1 | 0 |
|1 | 2 | 1 |
|2 | 1 | 1 |
|2 | 2 | 0 |
此表包含大约92000个评级(每行是一对唯一的三个)。我希望收到此表格的一部分,其中包含最活跃的用户和练习。最活跃的手段例如在表格中出现超过20次。所以我希望用户已经完成了20多个不同的练习,我希望不同用户完成20多次练习。
这是一个循环推理,因为我喜欢已完成20个或更多不同活动练习的用户,这些练习必须是活动的,因为它们应该由20个或更多用户和那些用户应该是活动的等等..
我希望通过查询可以实现这一点,我已经尝试过自己并提出了一个接近我想要的结果的查询,但结果并不完全准确(因为有一个用户)只完成了16次练习,2次练习已被其他用户完成19次)。查询有点难看,但现在是:
select UserID, ExerciseID, Score
from [FrenchExercises]
where ExerciseID in ( select ExerciseID
from [FrenchExercises]
where UserID in (SELECT UserID
FROM [FrenchExercises]
GROUP BY UserID
HAVING count(ExerciseID) >= 20)
group by ExerciseID
having count(UserID) >= 20)
AND UserID in ( select UserID
from [FrenchExercises]
where ExerciseIDin (SELECT ExerciseID
FROM [FrenchExercises]
GROUP BY ExerciseID
HAVING count(UserID) >= 20)
group by UserID
having count(ExerciseID) >= 20)
第一个子查询选择最活跃的用户,然后从活动用户列表中选择与用户最活跃的练习。第二个查询从练习角度做同样的事情,它选择最活跃的练习,然后选择选择这些练习的最活跃用户。当我想要结合两个查询并选择ExerciseID,UserID和Score时,我发现结果并不完全正确。
我猜测我的查询有些错误,或者我采取了完全错误的做法。任何想法都将不胜感激。
答案 0 :(得分:0)
根据一些评论进行编辑:
select userid, exerciseid, score
from frenchexercises
where userid in (select userid
from frenchexercises
group by userid
having count(*) >= 20)
and exerciseid in (select exerciseid
from frenchexercises
group by exerciseid
having count(distinct userid) >= 20)
小提琴演示: http://sqlfiddle.com/#!6/a2cc6/6/0
在示例数据中,我有USERID#1执行20次练习。练习#1到#20。这些练习中只有一个是活跃的"一。除了用户#1之外,练习#1由另外20个人执行,因此它是活动的。其余的不是。
在输出中返回用户#1,但仅列出练习#1,因为这是他执行的唯一活动练习。
此查询与我之前的查询之间的区别在于,用户#1不会被视为有效,因为他没有参与20个或更多个ACTIVE练习。他只参加了20个或更多的任何练习。这就是我改变的。
如果后者确实是你真正想要的,那么这是上一个查询:
select userid, exerciseid, score
from frenchexercises
where userid in (select userid
from frenchexercises
where exerciseid in
(select exerciseid
from frenchexercises
group by exerciseid
having count(distinct userid) >= 20)
group by userid
having count(*) >= 20)
and exerciseid in (select exerciseid
from frenchexercises
group by exerciseid
having count(distinct userid) >= 20)
同样,上述查询只会考虑用户是否活跃,如果他们也参加了20多个主动练习。
答案 1 :(得分:0)
我觉得我错过了一些细微差别,但对于我过于简单化的思想,这就是我所关注的:
我假设没有重复的UserID&此表中的ExcerciseID;因此,针对锻炼的用户数量是不同的,针对用户的锻炼计数是不同的。
我的方法是使用COUNT()OVER()来提供按记录提供的所需计数,然后过滤记录。
DECLARE @cutoff int
SET @cutoff = 20
SELECT
UserId
, ExerciseID
, Score
FROM (
SELECT
UserId
, ExerciseID
, Score
, COUNT(*) OVER (PARTITION BY UserID) AS ExcerciseUsers
, COUNT(*) OVER (PARTITION BY ExerciseID) AS UserExcercises
FROM FrenchExercises
) AS derived
WHERE ExcerciseUsers >= @cutoff
AND UserExcercises >= @cutoff
ORDER BY
UserId
, ExerciseID
;
Demo1 - small sample Demo2 - tast case by Brian DeMilia
在审查这个时,我可能忽略了“已经完成”,并且假设得分为1表示已完成,则以下内容将此考虑在内:
DECLARE @cutoff int
SET @cutoff = 5
SELECT
UserId
, ExerciseID
, Score
, ExcerciseUsers
, UserExcercises
FROM (
SELECT
UserId
, ExerciseID
, Score
, COUNT(*) OVER (PARTITION BY UserID) AS ExcerciseUsers
, COUNT(case when score = 1 then score end) OVER (PARTITION BY ExerciseID) AS UserExcercises
FROM FrenchExercises
) AS derived
WHERE ExcerciseUsers >= @cutoff
AND UserExcercises >= @cutoff
ORDER BY
UserId
, ExerciseID
;