SQL:子查询的列太多

SQL:子查询的列太多,sql,postgresql,Sql,Postgresql,我正在尝试使用postgresql进行查询。 该数据库包含两种关系:王国,其中包括一些英国国王,和迪纳斯蒂,其中包括一些来自斯图亚特迪纳斯蒂的人 王国的关系包括国王的名字以及他的王国开始和结束的时间。日常关系包括姓名、性别、出生和死亡 我想问的是,当国王去世时,他是最年长的一个 在我的查询中,我在第3行收到了这个错误:子查询的列太多 以下是查询: SELECT kingdom.king, dinasty.birth, dinasty.death FROM kingdom, dinasty WHE

我正在尝试使用postgresql进行查询。 该数据库包含两种关系:王国,其中包括一些英国国王,和迪纳斯蒂,其中包括一些来自斯图亚特迪纳斯蒂的人

王国的关系包括国王的名字以及他的王国开始和结束的时间。日常关系包括姓名、性别、出生和死亡

我想问的是,当国王去世时,他是最年长的一个

在我的查询中,我在第3行收到了这个错误:子查询的列太多

以下是查询:

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
);
NOT IN中的内容是正确的。

您在子查询中投影了三列,但在IN子句中比较了其中的一列。仅为子查询中的选择所需的列r1.king:

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将为每个distinct值取第一行,因此您必须将其与正确的ORDER BY配对。我们先按正午节的名字排序,然后按降序排列国王的寿命。这意味着在每一个节日中出现的第一位国王将是寿命最长的一位,这也是DISTINCT ON将在每一个节日中保留的记录

请注意,我还删除了与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
;
最后,如果需要在子选择中使用多列,可以使用行构造:

SELECT ...
  FROM table_a
  WHERE ROW(f1, f2, f3) NOT IN (SELECT f1a, f2a, f3a FROM ... )
;

此外,如果可以这样做,请尝试将子查询作为带有合适字段的派生表移动到from子句中,因为这样会更快,只计算一次,而不是每行计算一次。感谢您指出row选项!解决了我稍有不同的问题: