#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);
Результат:
Теперь я хочу составить запрос, который получит 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;