2016-09-22 64 views
0

3表選擇公共實體僅基於不同的對應實體

客戶端 -

CID Name 
1  Ana 
2  Bana 
3  Cana 

ClientProgram(橋接表) -

CID PID 
1  4 
1  5 
1  8 
2  10 

計劃 -

PID Program 
4  X 
5  Y 
8  Z 
10  G 

所需的輸出:

Name Program 
Ana  X 
Ana  Y 

我想只提取那些Clients這是常見的/在不同Programs我選擇存在(比如X和Y在這種情況下)

查詢嘗試:

SELECT 
     C.Name 
     ,P.Program 
    FROM ClientProgram CP 
    INNER JOIN Client C 
     ON CP.CID=C.CID 
    INNER JOIN Program P 
     ON CP.PID=P.PID 
    INNER JOIN ClientProgram CP1 
     ON CP.CID=CP1.CID 

    WHERE P.Program = 'X' OR P.Program = 'Y' 
     AND CP.CID = CP1.CID 

然而,這並不牽涉所有的客戶端,而且不僅僅是存在於多個程序中的客戶端。

+2

請把你的嘗試,以及,而不是僅僅要求一個答案。 –

回答

1
;WITH cte AS (
    SELECT 
     c.Name 
     ,p.Program 
     ,COUNT(*) OVER (PARTITION BY c.CID) as ProgramCount 
    FROM 
     Program p 
     INNER JOIN ClientProgram cp 
     ON p.PID = cp.PID 
     INNER JOIN Client c 
     On cp.CID = c.CID 
    WHERE 
     p.Program IN ('X','Y') 
) 

SELECT Name, Program 
FROM 
    cte 
WHERE 
    ProgramCount > 1 

在使用COUNT(*)將是一個問題,如果PID是不是程序或者CID以PID在ClientProgram組合不是唯一的獨一無二的。不過,我會根據我所看到的情況假定唯一性。

如果沒有,你可以去這樣的路線:

;WITH cte AS (
    SELECT 
     cp.CID 
    FROM 
     Program p 
     INNER JOIN ClientProgram cp 
     ON p.PID = cp.PID 
    WHERE 
     p.Program IN ('X','Y') 
    GROUP BY 
     cp.CID 
    HAVING 
     COUNT(DISTINCT p.PID) > 1 
) 

SELECT 
    c.Name 
    ,p.Program 
FROM 
    cte t 
    INNER JOIN Client c 
    ON t.CID = c.CID 
    INNER JOIN ClientProgram cp 
    ON t.CID = cp.CID 
    INNER JOIN Program p 
    ON cp.PID = p.PID 
    AND p.Program IN ('X','Y') 
0

這是關於這樣做的一種方式。可能是更好的方法,但這會做到這一點。我通過臨時表的腳本來防止其他人想要改進。例如可以做一個臨時表而不是CTE。

create table #client(cid int,name varchar(20)) 
create table #clientprogram (cid int, pid int) 
create table #program(pid int, program varchar(20)) 

insert into #client 
values(1,'Ana') 
    ,(2,'Bana') 
    ,(3,'Cana') 

insert into #clientprogram 
values (1,4) 
     ,(1,5) 
     ,(1,8) 
     ,(2,10) 
     ,(2,4) 

insert into #program 
values (4,'x') 
    ,(5,'y') 
    ,(8,'z') 
    ,(10,'g') 

WITH CHECKPLEASE AS(
Select c.Name,ISNULL(p.Program,p2.PRogram) Program 
from #client c 
inner join #clientprogram cp 
    on c.CID = cp.CID 
left join #program p 
    on cp.PID = p.PID 
    and p.PRogram = 'X' 
left join #program p2 
    on cp.PID = p2.PID 
    and p2.Program = 'Y' 
where ISNULL(p.Program,p2.PRogram) is not null 
) 

Select * 
From CHECKPLEASE 
where Name in (
SELECT Name 
From CHECKPLEASE 
group by Name 
having COUNT(*) > 1)