2011-04-11 136 views
2

我有以下表格:SQL - 多表連接並選擇條件的第一條記錄

Projects (ID, Name, ManagerUser_ID) 
Users(ID, Name, Active) 
Delegates(ProjectID, UserID, OrderNo) 

ManagerUser_ID是項目經理的項目,並且是用戶表的鏈接。用戶,但是可以是Inactive。因此,Delegates表是定義可以訪問項目數據的用戶的多對多表。

我需要的是爲Active的項目選擇第一個代表,假設經理爲InactiveOrderNo字段指定代表的順序(1代表第一位)。

一些樣本數據:

Project 
1, Project1, 2 
2, Project2, 4 
3, Project3, 1 

Users 
1, Joe, true 
2, John, false 
3, Dave, true 
4, Bob, false 

Delegates 
1, 4, 1 
1, 1, 2 
1, 3, 3 
2, 2, 1 
2, 4, 2 
2, 3, 3 

所以我查詢的輸出需要顯示:

Project1, Joe 
Project2, Dave 
Project3, Joe 

顯示項目和用戶對每一個項目,如果ManagerUser_ID是不活動的地方,然後選擇User in Delegates最低OrderNoActive

回答

1

這似乎這樣的伎倆(使用窗口功能)

SELECT P.Name, ISNULL(U.Name, FirstDelegate.Name) AS ProjManager 
FROM Projects P LEFT OUTER JOIN 
     Users U ON P.ManagerUser_ID = U.ID AND U.Active = 1 LEFT OUTER JOIN 
     (
      SELECT * FROM 
      (
       SELECT D.ProjectID, 
         US.Name, 
         ROW_NUMBER() OVER (PARTITION BY ProjectID ORDER BY OrderNo) AS SeqNo 
       FROM Delegates D INNER JOIN 
         Users US ON D.UserID = US.ID 
       WHERE US.Active = 1 
      ) AS Del 
      WHERE Del.SeqNo = 1 
     ) AS FirstDelegate ON P.ID = FirstDelegate.ProjectID 
0
select p.name, 
u.name, 
min(d.orderNo) 
from projects p, 
users u, 
users manager, 
delegates d 
where p.ManagerUser_ID = manager.id 
and manager.active = false 
and p.id = d.projectId 
and d.userid = u.id 
group by p.name, 
u.name 
+0

不幸的是,這並沒有收回項目的第一個活躍代表。這列出了該項目的所有用戶以及訂單號。需要在某個地方進行調用,將結果集限制爲處於活動狀態的最低OrderNo。 – Simon 2011-04-11 08:50:24

1

我認爲這將是這樣的事情。這個想法是做一個額外的連接(使用左連接)來找到一個更早的有效行。如果你能找到這一行,那麼很明顯你正在構建的當前行不是你想要一個:

select p.Name,m.Name from Projects p inner join Users m on p.ManagerUser_ID = m.ID and m.Active = 1 
union all 
select 
    p.Name, 
    u.Name 
from 
    Projects p 
     inner join 
    Delegates d 
     on 
      p.ID = d.ProjectID 
     inner join 
    Users u 
     on 
      d.UserID = u.ID and 
      u.Active = 1 
     left join 
    Delegates d_anti 
     inner join 
    Users u_anti 
     on 
      d_anti.UserID = u_anti.ID and 
      u_anti.Active = 1 
     on 
      p.ID = d_anti.ProjectID and 
      d_anti.OrderNo < d.OrderNo 
where 
    u_anti.ID is null 
+0

這看起來非常接近,生病必須明天檢查。但是,最後的ON子句不正確 - u_anti.OrderNo Simon 2011-04-11 10:03:34

+0

@Simon - 是的,你會在那裏正確的。 – 2011-04-11 11:41:56

1
Select projectName, userName 
From 

(
    Select projectName, userName, row_number() over (partition by projectName order by priority ASC) as rank 
    From 
    (
     SELECT p.name as projectName, u.name as userName, 1 as priority 
     FROM projects p INNER JOIN users u ON u.active = true and u.id = p.ManagerUser_ID 

     UNION 

     SELECT TOP(1) p.name, u.name, 2 
     FROM Delegates d INNER JOIN projects p ON p.id = d.projectId 
         INNER JOIN users u ON u.id = d.userId 
     Where u.active = true 
     Order by u.OrderNo ASC 
    ) 
) 
where rank = 1