2011-06-13 8 views
6

Disculpa por el tema incorrecto. No podría pensar en uno mejor y estoy apurado.Función de agregación que selecciona el valor de una columna que corresponde a otras funciones agregadas exitosas que coinciden

decir que tengo las siguientes tablas:

Padres

  • Id
  • Nombre
  • ...

Niño

  • Id
  • parentid
  • Edad
  • ...

hay una relación de uno a varios entre padres e hijos.

Ahora quiero construir una consulta que devuelva a todos los padres y a su hijo menor. Quiero que el resultado sea así:

Resultado

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

Hay también debe ser sólo una fila por Parent.Id en el resultado.

Aquí es una imagen que explica lo que quiero

http://i.stack.imgur.com/L6PjL.png

Aquí es donde estoy ahora:

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 

Lo que yo quiero es una función agregada para poner alrededor del niño. Id que obtendría Child.Id que corresponde a la fila que es MIN (Child.Age). No puedo encontrar tal cosa y no puedo emular el comportamiento.

¡Cualquier ayuda es muy apreciada!

+0

El sistema requiere que tengas cierta reputación antes de permitir imágenes en línea, pero estoy seguro de que no pasará mucho tiempo hasta que tengas eso. He editado para poner tu imagen en línea para ti. – AakashM

+0

Sí, me lo dijo. Razonable. Gracias por la edición! :) –

Respuesta

6

Su idea de usar OVER con un PARTITION BY ParentId está en la dirección correcta; sin embargo, en lugar de usarlo con MIN, úselo con un ROW_NUMBER() para obtener toda la fila. Este:

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

declaraciones de todos los niños, junto con un número de fila que indican su orden de edad dentro hijos de un mismo padre, por lo que sólo tenemos que filtrar que:

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 

Nota que Mientras solicita "todos los padres y su hijo menor", es posible que desee considerar lo que desea devolver para los registros en Parent con no registros coincidentes en Child - mi solución, junto con todos los demás, no incluirán información sobre tales registros Parent.

+0

+1 para explicar la respuesta. –

1
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 

) 
-1

Ésta podría funcionar:

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 
-2

Usted puede intentar algo como esto:

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

Tenga en cuenta que es posible que más de un niño por sus padres (si tienen la misma , edad mínima).

+0

d'oh, llegué demasiado tarde :) – Vincent

+1

Vuelva a verificar su consulta. No es correcto. "id" no le pertenece al niño. También hay otros problemas. –

1
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 
Cuestiones relacionadas