找到每个父级的最高值

时间:2010-08-16 17:17:14

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

我确信这是一个常见的请求,但我不知道如何正式提出要求。

我很久以前在陆军时遇到过这个问题。士兵有多次身体健康测试,但主要测试是最近的。士兵还具有多种射击资格,但只有最近获得武器的资格才具有重要意义。

如何创建一个列出父项最重要子项的视图?

3 个答案:

答案 0 :(得分:1)

使用:

  SELECT p.*, x.*
    FROM PARENT p
    JOIN CHILD x ON x.parent_id = p.id
    JOIN (SELECT c.id,
                 c.parent_id,
                 MAX(c.date_column) AS max_date
            FROM CHILD c
        GROUP BY c.id, c.parent_id) y ON y.id = x.id
                                     AND y.parent_id = x.parent_id
                                     AND y.max_date = x.date

假设SQL Server 2005 +:

WITH summary AS (
     SELECT p.*, 
            c.*, 
            ROW_NUMBER() OVER (PARTITION BY p.id 
                                  ORDER BY c.date DESC) AS rank
       FROM PARENT p
       JOIN CHILD c ON c.parent_id = p.id)
SELECT s.*
  FROM summary s
 WHERE s.rank = 1

答案 1 :(得分:1)

虽然我不太清楚“逐项”暗示你的意思,但你可以这样做:

Select ..
From Soldier
    Left Join FitnessTest
        On FitnessTest.SoldierId = Soldier.Id
            And FitnessTest.TestDate =  (
                                        Select Max(FT1.TestDate)
                                        From FitnessTest As FT1
                                        Where FT1.SoldierId = FitnessTest.SoldierId
                                        )
    Left Join MarksmanshipTest
        On MarksmanshipTest.SoldierId = Soldier.Id
            And MarksmanshipTest.TestDate = (
                                            Select Max(MT1.TestDate)
                                            From MarksmanshipTest As MT1
                                            Where MT1.SoldierId = MarksmanshipTest.SoldierId
                                            )

这假设一名士兵在健身测试或射击测试中不能有两个测试日期时间值。

答案 2 :(得分:0)

与前两个答案没有显着差异,但可能会有更多细节:

create table soldier ( soldierId int primary key,
    name varchar(100) )
create table fitnessTest ( soldierId int foreign key references soldier,
    occurred datetime, result int )
create table marksmanshipTest ( soldierId int foreign key references soldier,
    occurred datetime, result int )

;with
mostRecentFitnessTest as
(
    select
        fitnessTest.soldierId,
        fitnessTest.result,
        row_number() over (order by occurred desc) as row
    from fitnessTest
),
mostRecentMarksmanshipTest as
(
    select
        marksmanshipTest.soldierId,
        marksmanshipTest.result,
        row_number() over (order by occurred desc) as row
    from marksmanshipTest
)
select
    soldier.soldierId,
    soldier.name,
    mostRecentFitnessTest.result,
    mostRecentMarksmanshipTest.result
from soldier
    left outer join mostRecentFitnessTest on
        mostRecentFitnessTest.soldierId = soldier.soldierId
        and mostRecentFitnessTest.row = 1
    left outer join mostRecentMarksmanshipTest on
        mostRecentMarksmanshipTest.soldierId = soldier.soldierId
        and mostRecentMarksmanshipTest.row = 1