我无法实现看起来应该简单的事情。下面的示例显示了在课程中注册的人员,一个人可以注册多个班级,但目前只有一个班级:
DECLARE @Test TABLE
(
PersonId int NOT NULL,
LocationId int NOT NULL,
ClassId int NOT NULL,
IsEnrolled bit NOT NULL,
IsExited bit NOT NULL
)
添加数据:
INSERT INTO @Test
SELECT 1,5,6,1,0
UNION SELECT 1,6,7,0,1
UNION SELECT 2,5,8,1,0
UNION SELECT 2,5,9,0,1
UNION SELECT 3,5,9,0,1
UNION SELECT 3,6,9,1,0
我想获取所有注册位于同一位置(具有相同LocationId)的人的所有记录(当前与否),但只有当前值(IsEnrolled = 1)所在的位置是不同的。 对于同一个PersonId,如果LocationId是唯一的,我想要所有记录,如果LocationId对于PersonId不是唯一的,则只有当前(IsEnrolled = 1)。
我希望从查询中获取数据:
SELECT
1 AS PersonId,
6 AS ClassId,
1 As IsEnrolled,
0 AS IsExited
UNION SELECT 2, 8, 1, 0
UNION SELECT 2, 9, 0, 1
UNION SELECT 3, 9, 1, 0
答案 0 :(得分:1)
以下是您可以使用的一种方法:
SELECT *
FROM
(
SELECT
*,
(SELECT COUNT(DISTINCT t2.LocationID) FROM tab t2 WHERE t2.PersonId = t1.PersonId) AS LocationCount
FROM tab t1
) t
WHERE
t.LocationCount = 1 --get all records for those at the same location
OR (t.LocationCount > 1 AND t.IsEnrolled = 1) --get only current records for those @ multiple location
基本上,您可以计算某人注册的位置。如果它们只是一个,则记录所有记录,如果多个只记录当前的记录。
答案 1 :(得分:1)
我认为它比以前尝试的方法简单得多:
SELECT Test.*
FROM @Test Test
JOIN
(
SELECT PersonID, LocationID
FROM @Test T
WHERE ISENROLLED = 1
GROUP BY PeronID, LocationID
) T
ON Test.PersonID = T.PersonID
AND Test.LocationID = T.LocationID
因为你只能有一个" isenrolled"每人记录,内部查询保证为每个人返回一个人/位置组合。因此,在人员和位置上加入它可以确保您获得当前注册课程所在位置的每个人的记录。
答案 2 :(得分:1)
如果我理解正确,您希望所有记录都是最新的或属于一直位于同一位置的人。因此:
select personid, classid, isenrolled, isexited
from mytable
where isenrolled = 1
or personid in
(
select personid
from mytable
group by personid
having min(locationid) = max(locationid)
)
order by personid, classid;
与窗口函数相同,因此必须只读取一次表:
select personid, classid, isenrolled, isexited
from
(
select
personid, classid, isenrolled, isexited,
min(locationid) over (partition by personid) as minloc,
max(locationid) over (partition by personid) as maxloc
from mytable
)
where isenrolled = 1 or minloc = maxloc
order by personid, classid;
答案 3 :(得分:0)
您可以使用聚合查询获取personid
:
select personid
from @test t
where isenrolled = 1
group by personid
having min(location) = max(location);
此时,使用in
来获取其他所有内容非常容易:
select t.*
from @test t
where personid in (select personid
from @test t
where isenrolled = 1
group by personid
having min(location) = max(location)
);
答案 4 :(得分:0)
一次加入
select t2.PersonId, t2.ClassId, t2.IsEnrolled, t2.IsExited
from @Test t1
left join @Test t2
on t2.PersonId = t1.PersonId
and ((t2.IsEnrolled = 0 and t2.LocationId <> t1.LocationId)
or (t2.IsEnrolled = 1)
)
where t1.IsEnrolled = 1