SQL - 帮助“按组排名第一”

时间:2010-01-13 01:24:38

标签: sql-server tsql greatest-n-per-group

相关表格:
DepartmentPhone:DepartmentPhoneID int,DepartmentID int,PhoneID int
电话:PhoneID int,PhoneType int

PhoneType = 4的手机有6部属于DepartmentID = 2。所以这产生了6条记录:

select *
from DepartmentPhone
  join Phone on Phone.PhoneID = DepartmentPhone.PhoneID and Phone.PhoneType = 4
where DepartmentPhone.DepartmentID = 2

请注意,DepartmentID = 2仅用于说明目的,我的查询将带来所有部门 我想要实现的是为每个部门选择第一部电话(类型= 4) - 每个部门只有1行。我认为以下查询可以解决问题,但它会继续检索所有6条记录。我错过了什么?

select x.*
from DepartmentPhone x
where 
  x.DepartmentID = 2
  and x.PhoneID = (select max(y.PhoneID)
                   from departmentphone y 
                     join Phone on y.PhoneID = Phone.PhoneID and Phone.PhoneType = 4
                   where x.DepartmentPhoneID = y.DepartmentPhoneID)

感谢您的帮助!!!

2 个答案:

答案 0 :(得分:2)

我希望 是一个干净的语法。最好的方法是使用ROW_NUMBER

;WITH DepartmentPhone_CTE AS
(
    SELECT p.*, 
        ROW_NUMBER() OVER
            (PARTITION BY dp.DepartmentID ORDER BY dp.PhoneID) AS RowNum
    FROM DepartmentPhone dp
    INNER JOIN Phone p
        ON p.PhoneID = dp.PhoneID
    WHERE p.PhoneType = 4
)
SELECT dp.*
FROM DepartmentPhone_CTE
WHERE RowNum = 1

答案 1 :(得分:0)

我不了解您的架构,但我猜您需要按DepartmentID关联您的分组,而不是DepartmentPhoneID

select x.*
from DepartmentPhone x
where 
  x.DepartmentID = 2
  and x.PhoneID = (select max(y.PhoneID)
                   from departmentphone y 
                     join Phone on y.PhoneID = Phone.PhoneID and Phone.PhoneType = 4
                   where x.DepartmentID = y.DepartmentID);

这里有几个替代查询,它们应该在不使用相关子查询的情况下得到相同的结果。第一个使用派生表:

select *
from DepartmentPhone x
join (select d.DepartmentID, max(d.PhoneID) as maxPhoneID
      from DpartmentPhone d join Phone p using (PhoneID)
      where p.PhoneType = 4
      group by d.DepartmentID) y
  using (DepartmentID);

第二种方法根本不使用子查询,而是使用自连接:

select d1.*
from DepartmentPhone d1
join Phone p1 on d1.PhoneID = p1.PhoneID and p1.PhoneType = 4
left outer join (DepartmentPhone d2 join Phone p2 
    on d2.PhoneID = p2.PhoneID and p2.PhoneType = 4)
  on d1.DepartmentID = d2.DepartmentID and d1.PhoneID < d2.PhoneID
where d2.DepartmentID is NULL;