SQL: подзапрос имеет слишком много столбцов
Я пытаюсь сделать запрос с помощью postgresql. База данных содержит два отношения:" Королевство", в которое входят некоторые английские короли, и" династия", в которой содержатся некоторые люди из династии Стюарта
отношение "королевство" включает в себя имя короля и когда его королевство началось и закончилось. Отношение "династия" включает в себя имя, пол, рождение и смерть.
С моим запросом я получение этой ошибки в строке 3 (не в):subquery has too many columns
Это запрос:
SELECT kingdom.king, dinasty.birth, dinasty.death
FROM kingdom, dinasty
WHERE kingdom.king = dinasty.name AND kingdom.king NOT IN
(
SELECT DISTINCT R1.king, R1.birth, R1.death
FROM
(
SELECT DISTINCT R1.king, D1.birth, D1.death
FROM kingdom AS R1, dinasty AS D1, dinasty AS D2
WHERE R1.king=D1.name
) AS R1,
(
SELECT DISTINCT R1.king, D1.birth, D1.death
FROM kingdom AS R1, dinasty AS D1, dinasty AS D2
WHERE R1.king=D1.name
) AS R2
WHERE R1.death-R1.birth < R2.death-R2.birth
);
то, что находится внутри не в правильно.
2 ответов
вы проецируете три столбцы в вашем подзапросе, но сравнение одного один их в IN
предложения. Выберите только необходимый столбец (r1.king
) для IN
в подзапросе:
SELECT kingdom.king, dinasty.birth, dinasty.death
FROM kingdom, dinasty
WHERE kingdom.king = dinasty.name AND kingdom.king NOT IN
(
SELECT DISTINCT R1.king
FROM
(
SELECT DISTINCT R1.king, D1.birth, D1.death
FROM kingdom AS R1, dinasty AS D1, dinasty AS D2
WHERE R1.king=D1.name
) AS R1,
(
SELECT DISTINCT R1.king, D1.birth, D1.death
FROM kingdom AS R1, dinasty AS D1, dinasty AS D2
WHERE R1.king=D1.name
) AS R2
WHERE R1.death-R1.birth < R2.death-R2.birth
);
как было сказано, количество столбцов не совпадало, но есть гораздо более простой способ написать это.
при написании запросов лучше всего продумывать их поэтапно. Во-первых, вам нужно знать, сколько лет было каждому королю, когда они умерли:
SELECT *, death-birth AS lived_for FROM dinasty
теперь, когда у вас есть это, вы можете использовать DISTINCT ON, чтобы найти самого долгоживущего короля для каждого королевства
SELECT DISTINCT ON( name ) name, birth, death, lived_for
FROM (
SELECT *, death-birth AS lived_for FROM dinasty
) a
ORDER BY name, lived_for DESC
;
distinct on будет принимать первую строку для каждого отдельного значения, поэтому важно, чтобы вы связали его с правильный ORDER BY
. Сначала мы заказываем по имени династии, затем, как долго жил король в порядке убывания. Это означает, что первый король, показанный для каждой династии, будет самым долгоживущим, и это запись, которая будет сохраняться для каждой династии.
обратите внимание, что я также удалил соединение с kindgom, но при необходимости вы можете добавить его обратно:
SELECT k.*, oldest.*
FROM (
SELECT DISTINCT ON( name ) name, birth, death, lived_for
FROM (
SELECT *, death-birth AS lived_for FROM dinasty
) a
ORDER BY name, lived_for DESC
) oldest
JOIN kingdom k ON k.king = oldest.name
;
наконец, если вам когда-либо нужно использовать несколько столбцов в под-выборе, вы можете использовать ROW () construct:
SELECT ...
FROM table_a
WHERE ROW(f1, f2, f3) NOT IN (SELECT f1a, f2a, f3a FROM ... )
;