使用group by子句从具有最大值的行获取另一个值

时间:2018-06-06 22:51:20

标签: sql sql-server

对不起标题。我有这张桌子:

CREATE TABLE people
(
    Id int IDENTITY(1,1) PRIMARY KEY,
    name varchar(50) NOT NULL,
    FatherId int REFERENCES people(Id),
    MotherId int REFERENCES people(Id),
    age int NOT NULL
);

您可以使用以下命令填充:

insert into people (name, age) VALUES ('Jonny', 50 )
insert into people (name, age) VALUES ('Angela', 48 )
insert into people (name, age) VALUES ('Donny', 55 )
insert into people (name, age) VALUES ('Amy', 55 )
insert into people (name, FatherId, MotherId, age) VALUES ('Marcus', 1, 2, 10)
insert into people (name, FatherId, MotherId, age) VALUES ('Beevis', 1, 2, 5)
insert into people (name, FatherId, MotherId, age) VALUES ('Stew', 3, 4, 24)
insert into people (name, FatherId, MotherId, age) VALUES ('Emily', 3, 4, 25)

我的目标

我想获得每组父母中最大孩子的年龄名称。

获得年龄非常简单:

SELECT MAX(age) FROM people WHERE FatherId IS NOT NULL GROUP BY FatherId

但是如果我想让年龄得到相应的名字怎么办?

我试过

select p1.name, p1.age
FROM people p1
INNER JOIN
(
SELECT FatherId, MAX(age) age
FROM people
GROUP BY FatherId
) p2
ON p1.FatherId = p2.FatherId

但是这只是因为FatherId匹配而给所有孩子。

由于GROUP BY子句,我似乎无法获得主键(Id)。

我想如果这是不可能的,那么可能需要进行一些表格重组才能实现?

修改

以下是我使用CROSS APPLY

找到的解决方案
select child.name, child.age
FROM people parents
CROSS APPLY
(
    select top 1 age, name
    from people child
    where child.FatherId = parents.Id
    ORDER BY age DESC
) child

4 个答案:

答案 0 :(得分:1)

这是对您自己尝试的简单调整。这样做的一个可能的优点就是允许联系。

JTable table = new JTable( model ) {
  public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
    Component c = super.prepareRenderer(renderer, row, column);

    //  Alternate row color
    if (!isRowSelected(row)) {
      c.setBackground(row % 2 == 0 ? getBackground() : Color.LIGHT_GRAY);
    }
    return c;
  }
};

你也确实参考过#34;父母和#34;在问题中。要做到这一点,你需要分组并加入select p1.name, p1.age from people p1 inner join ( select FatherId, max(age) max_age from people group by FatherId ) p2 on p2.FatherId = p1.FatherId and p2.max_age = p1.age; ,当然假设这与儿童通常只有一个共同父母的现实世界相匹配。

答案 1 :(得分:0)

您可以尝试此查询并查看 demo

select 
name,age
from
(select p.*, rn=row_number() over(partition by p.fatherid,p.motherid order by age desc) from 
people p join
(select fatherid,motherid from people
where coalesce(fatherid,motherid) is not null
group by fatherid,motherid)t
on p.fatherid=t.fatherid and p.motherid=t.motherid
)t where rn=1

答案 2 :(得分:0)

两个nested sub-select语句可与inner join结合使用:

SELECT p1.age, p2.name
  FROM 
(
SELECT max(age) age
  FROM people 
 WHERE FatherId is not null
 GROUP BY FatherId ) p1
 INNER JOIN
(
SELECT age, name
  FROM people 
 WHERE FatherId is not null ) p2
 ON ( p1.age = p2.age );

age name
--- ------
10  Marcus
25  Emily

SQL Fiddle Demo

答案 3 :(得分:0)

这将接纳双方父母

declare @t TABLE 
(
    Id int IDENTITY(1,1) PRIMARY KEY,
    name varchar(50) NOT NULL,
    FatherId int,
    MotherId int,
    age int NOT NULL
);
insert into @t (name, age) VALUES 
('Jonny', 50 ),
('Angela', 48 ),
('Donny', 55 ),
('Amy', 55 );
insert into @t (name, FatherId, MotherId, age) VALUES 
('Marcus', 1, 2, 10),
('Beevis', 1, 2, 5),
('Stew', 3, 4, 24),
('Emily', 3, 4, 25);

select tt.name, tt.age
     , tt.fatherName, tt.fatherAge
     , tt.motherName, tt.motherAge
from (
select ta.*
     , tf.name as fatherName, tf.age as fatherAge 
     , tm.name as motherName, tm.age as motherAge
     , row_number() over (partition by ta.FatherID, ta.MotherID order by ta.age desc) as rn
from @t ta 
left join @t tf 
  on tf.id = ta.fatherID
left join @t tm 
  on tm.id = ta.motherID 
  ) as tt 
where FatherID is not null 
  and rn = 1