SQL: создать глобальный псевдоним для вложенного ВЫБОРА, который будет использоваться в другом вложенном ВЫБОРЕ

#mysql #sql #select #nested-select

#mysql #sql #выберите #вложенный выбор

Вопрос:

Давайте предположим, что у меня есть база данных с двумя таблицами: people которая содержит идентификатор пользователя и год его / ее рождения для каждого человека и parents которая содержит (parent_id, child_id) пары для представления относительных отношений между людьми. Чтобы упростить объяснение, давайте предположим, что у каждого пользователя есть либо 0 дочерних элементов, либо 1 дочерний элемент. Вот пример данных в базе данных (в виде набора инструкций SQL для их создания в MySQL):

 CREATE TABLE people (
    id  INTEGER NOT NULL AUTO_INCREMENT,
    birth_year  INTEGER NOT NULL,
    CONSTRAINT PRIMARY KEY(id)
);

CREATE TABLE parents (
    parent_id   INTEGER NOT NULL,
    child_id    INTEGER NOT NULL,
    CONSTRAINT PRIMARY KEY(parent_id,child_id)
);

-- Not creating FOREIGN KEYS, because it's just an example

INSERT INTO people (id, birth_year) VALUES (1, 1937);
INSERT INTO people (id, birth_year) VALUES (2, 1943);
INSERT INTO people (id, birth_year) VALUES (3, 1974);
INSERT INTO people (id, birth_year) VALUES (4, 2001);
INSERT INTO people (id, birth_year) VALUES (5, 2020);

INSERT INTO parents (parent_id, child_id) VALUES (1, 4);
INSERT INTO parents (parent_id, child_id) VALUES (3, 5);
  

Результат:

Таблица people

Родительская таблица

Теперь я хочу составить запрос, который получит id имя человека, чей ребенок родился в самом раннем возрасте родителя (например, если я родился в 1234 году, а мой ребенок родился в 1300 году, тогда мой возраст, когда родился мой ребенок, был 1300 - 1234 = 66 , и я хотел бы найтичеловек, который получил своего ребенка раньше других).

Я составил для него несколько запросов, но каждый из них либо не работал, либо имел дублирование, либо и то, и другое. Мне больше всего нравится

 SELECT id AS pid, -- Parent id
(SELECT child_id FROM parents WHERE parent_id=pid) AS cid -- Child id
FROM people WHERE
EXISTS(SELECT cid) -- Only selecting parents who have children (not sure this part is correct)
ORDER BY (birth_year - (SELECT birth_year FROM people WHERE id=cid)) ASC -- Order by age when they got their child
LIMIT 1;
  

Но этот сбой в MySQL с ошибкой:

 ERROR 1054 (42S22) at line 24: Unknown column 'cid' in 'field list'
  

Как мне исправить ошибку? Еще одна вещь, о которой я беспокоюсь, это то, что в результате я выберу не только идентификатор родителя, но и идентификатор одного из его / ее дочерних элементов. Можно ли этого избежать?
Возможно, есть лучший способ выбрать данные, которые я ищу?

Ответ №1:

Вы можете получить возраст с помощью объединений:

 select c.*, (p.birth_year - c.birth_year) as parent_age 
from parents pa join
     people p
     on pa.parent_id = p.id join
     people c
     on pa.child_id = pc.id;
  

Чтобы получить все строки с минимальным значением, используйте оконные функции:

 select x.*
from (select c.*, (p.birth_year - c.birth_year) as parent_age,
             min(p.birth_year - c.birth_year) over () as min_age
      from parents pa join
           people p
           on pa.parent_id = p.id join
           people c
           on pa.child_id = pc.id
     ) x
where parent_age = min_age;