2016-05-17 11 views
0

我無法實現看起來應該很簡單的事情。下面的例子表明,人們參加班,一個人可以在多個類別中註冊,但只有一個目前:從具有分組ID的表中選擇值,但在非分組列中有差異

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唯一,並且只有當前(IsEnrolled = 1),如果LocationId對PersonId不唯一,則需要所有記錄。

數據我想從一個查詢回:

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

首先,你可以定義如何確定「的人「?是否「Id」是個人ID「?否則,我無法看到如何跟蹤這些記錄中的個人。此外,您是否可以更詳細地定義」他們的所有入學都在同一地點?「的含義?這意味着對於Id(假設這是PersonId)的每個組(記錄窗口)是相同的並且LocationId是相同的,該窗口中的所有記錄都被標記爲IsEnrolled? –

+0

@magnum_pi - 爲了澄清而將其重命名爲Id ,'在相同的位置'意味着LocationId在行中是相同的。謝謝 – Noel

+0

您對我期望的結果的描述不清楚。「所有登記在同一地點的所有記錄」。從您的樣本數據中,只有Person2應具有資格。和「當前位置不同」,我不知道這意味着什麼。 –

回答

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 

既然你只能hav每個人一個「登記」記錄,內部查詢保證爲每個人返回一個人/位置組合。因此,加入人員和地點可確保您獲得該人員在當前已註冊班級所在位置的每條記錄。

+0

也許吧。我把這個任務理解爲「接受當前的」,加上「當他們全部在同一個位置時接受其他人」。你理解爲「採取當前」,加上「採取與當前位於同一位置的其他人」。 –

+0

@ThorstenKettner是的,有語言障礙,他沒有澄清他的問題。 –

+1

實際查詢比我發佈的要複雜一些,但這個答案讓我在需要的地方。 – Noel

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 

從本質上講,你算一個人在被錄取的位置。如果他們只是一個人,那麼記錄所有記錄,如果多個記錄只記錄當前登記。

+0

一個很好的解決方案。儘管如此,從來沒有在WHERE條款中加入CASE WHEN。這隻會使條款複雜化。你的'WHERE'子句很簡單:'WHERE LocationCount = 1 OR(LocationCount> 1 AND IsEnrolled = 1)'仍然可以簡化爲'WHERE LocationCount = 1或IsEnrolled = 1'。 –

+0

@ThorstenKettner你說得對。我過度思考。現在已經糾正了。 – morgb

0

可以使用聚合查詢得到personid S:

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) 
       ); 
+0

該查詢總是返回所有記錄,其中IsEnrolled = 1。移除WHERE子句可以獲取位置相同的所有記錄,因此我可以在兩部分查詢中獲取它。 – Noel

+0

@Noel。 。 。只需從外部查詢中移除'isenrolled'條件即可。我不確定你想要返回哪條記錄。 –

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; 
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 
相關問題