开发者

Aggregate function that selects the value of a column that corresponds to another successful aggregate functions match

Sorry about the bad subject. I couldn't think of a better one and I'm in a hurry.

Say i have the following tables:

Parent

  • Id
  • Name
  • ...

Child

  • Id
  • ParentId
  • Age
  • ...

There is a One-to-Many relation between parent and child.

Now I want to construct a query that returns all parents and their youngest child. I want the result to be like this:

Result

  • Parent.Id
  • Child.Id
  • Child.Age

There should also be only one row per Parent.Id in the result.

Here is an image that explains what i want

Aggregate function that selects the value of a column that corresponds to another successful aggregate functions match

This is where I am right now:

SELECT   
Parent.Id AS ParentId,
Child.Id AS ChildId, 
MIN(Child.Age) AS ChildAge -- OVER (PARTITION BY Parent.Id) AS ChildAge
FROM Parent JOIN Child ON Parent.Id = Child.ParentId
GROUP BY Parent.Id, Child.Id

What I would wa开发者_如何学Gont is an aggregate function to put around Child.Id that would fetch the Child.Id that corresponds to the row that is MIN(Child.Age). I can't find any such thing and i can't seem to emulate the behavior.

Any help is much appreciated!


Your idea of using OVER with a PARTITION BY ParentId is in the right direction; however, rather than use it with MIN, use it with a ROW_NUMBER() to get at the whole row. This:

SELECT
    ParentId
    , Id
    , Age
    , ROW_NUMBER() OVER ( PARTITION BY ParentId ORDER BY Age ) AS rn
FROM Child

returns all children, along with a row number indicating their age order within children of the same parent, so we just need to filter that:

SELECT ParentId, Id, Age FROM (
    SELECT
        ParentId
        , Id
        , Age
        , ROW_NUMBER() OVER ( PARTITION BY ParentId ORDER BY Age ) AS rn
    FROM Child
) c   -- need to alias the subquery in order to SELECT from it
WHERE rn = 1


ParentId    Id          Age
----------- ----------- -----------
1           11          2
2           13          4
3           15          3
4           19          1

Note that while you ask for "all parents and their youngest child", you may want to consider what you want returned for records in Parent with no matching records in Child - my solution, along with all the others, will not include any information about such Parent records.


SELECT   
Parent.Id AS ParentId,
C.Id AS ChildId, 
C.Age AS ChildAge 
FROM Parent, CHILD C
WHERE PARENT.ID = C.ParentId
AND C.AGE = 
(
    SELECT MIN(AGE)
    FROM CHILD
    WHERE ParentId = C.ParentId

)


SELECT   
    Parent.Id AS ParentId,
    Child.Id  AS ChildId, 
    Child.Age AS ChildAge 
FROM Parent
  JOIN Child 
    ON Parent.Id = Child.ParentId
  JOIN
    ( SELECT ParentId,
             MIN(Age) AS ChildAge
      FROM Child
      GROUP BY ParentId   
    ) AS minCh
    ON Child.ParentId = minCh.ParentId
    AND Child.Age = minCh.ChildAge


This one might work:

SELECT
ParentID,
ChildId,
ChildAge
FROM
(

SELECT   
Parent.Id AS ParentId,
Child.Id AS ChildId, 
MIN(Child.Age) AS ChildAge,   
Ranking  = ROW_NUMBER() OVER(PARTITION BY  ParentID order by Child.Age asc)  

FROM Parent JOIN Child ON Parent.Id = Child.ParentId
GROUP BY Parent.Id, Child.Id, Child.Age
)A
Where Ranking =1


You may try something like this:

SELECT parentid, id, age FROM child c
 WHERE age = (SELECT MIN(c2.age) FROM child c2 WHERE c2.parentid = c.parentid);

Note that you may find more than one child per parent (if they have the same, minimal age).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜