Оператор SQL: средний - PullRequest
       13

Оператор SQL: средний

0 голосов
/ 06 ноября 2019

Мой вопрос: каков средний возраст, чтобы стать первым дедушкой. Решение должно быть выдано как Average_age. День, когда человек становится дедушкой, - это место, где родился его первый внук.

Отношения:

human (name, gender, age) 
parent (ParentName, ChildName) -> is subset of human(name).

Таблица:

enter image description here enter image description here

IВы знаете, что дедушка - это человек, у которого есть родительское имя и ребенок от имени ребенка, который также является человеком (отцом) с именем родителя, у которого есть дети от имени ребенка (внуки). Теперь проблема в том, как мне получить средний возраст, чтобы стать дедушкой.

Что я получил до сих пор:

SELECT AVG(age) as average_age
FROM human h JOIN
     parent p
     ON h.name = p.parentname
WHERE h.gender = 'm' AND p.parentname = p.childname AND h.name = p.parentname

Ожидаемый результат:

average_age : 52

Ответы [ 3 ]

1 голос
/ 06 ноября 2019

Чрезвычайно необычно хранить ВОЗРАСТ людей в столе, потому что это меняется - каждый день. Данные должны храниться с датой рождения.

Это запрос агрегации, но вам нужно присоединиться к таблицам несколько раз. Чтобы получить бабушку и дедушку, вам нужно объединиться за столом parents. Затем вам нужно ввести humans для фильтрации:

select avg(min_age * 1.0)
from (select min(h_grandparent.age - h.grandchild.age) as min_age
      from parent p join  -- p.parentname is the grandparent
           parent pchild
           on p.childname = pchild.parentname join
           human h_grandparent
           on p.parentname = h_grandparent.name join
           human h_grandchild
           on pchild.childname = h_grandchild.name
      where h_grandparent.gender = 'm'
      group by h_grandparent.name
     ) a
0 голосов
/ 06 ноября 2019

Вы можете сделать это еще с 2 join s и вычесть возраст самого большого внука:

SELECT AVG(p_age) average_age
FROM
(
    SELECT  h.name, h.age-MAX(h2.age) as p_age
    FROM parent p1 
        LEFT JOIN parent p2 ON P1.childname = P2.parentname
        INNER JOIN human h ON P1.parentname = h.name
        INNER JOIN human h2 ON P2.ChildName = h2.name
    WHERE h.gender = 'm' AND p2.childname IS NOT NULL
    GROUP BY h.name, h.age
)pAges

Пожалуйста, учтите, что имя не подходит для данных задач.

0 голосов
/ 06 ноября 2019

Я бы решил это с помощью условия exists, которое фильтрует людей, у которых есть внуки:

select avg(age) avg_age_of_grandpas
from human h
where 
    gender = 'm'
    and exists (
        select 1
        from parent p1
        inner join parent p2 on p2.parentName = p1.childName
        where p1.parentName = h.name
    )

Условие exists гарантирует, что у этого человека будет хотя бы один ребенок и один внучатый ребенок. Внешний запрос вычисляет среднее значение таких людей. Учитывая информацию, доступную в структуре вашей таблицы, это кажется мне наиболее логичным подходом. В отличие от join s, использование exists позволяет избежать дублирования записей (и получить неверные результаты в среднем), когда у человека более одной строки потомков.


Если вы хотите указать возрастпрародитель в день, когда родился их первый внучат, тогда это немного сложно. Это должно приблизить вас к тому, что вы ожидаете:

select avg(h.age - g.maxGrandChildAge) avg_age_of_grandpas
from human h
inner join (
    select 
        p1.parentName grandParentName, 
        max(h1.age) maxGrandChildAge
    from parent p1
    inner join parent p2 on p2.parentName = p1.childName
    inner join human h1 on h1.name = p2.childName
) g
on g.grandParentName = h.name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...