缺少表的 FROM 子句条目

问题描述 投票:0回答:3

我编写了以下 SQL 语句来从两个表中获取数据

gendata
&
TrainingMatrix
:

SELECT * FROM (SELECT DISTINCT ON ("TrainingMatrix".payroll, "TrainingName", "Institute")"gendata"."Employee Name","gendata"."Position", "gendata"."Department",  "TrainingMatrix".* 
FROM "TrainingMatrix" JOIN "gendata" ON "TrainingMatrix".payroll = "gendata".payroll 
ORDER  BY payroll, "TrainingName", "Institute" ,"TrainingDate" DESC NULLS LAST) AS foo;

它工作正常,但我需要通过以下方式更多地过滤记录:

WHERE "TrainingMatrix"."ExpiryDate" - current_date <= 0 
AND  EXTRACT(YEAR FROM  "TrainingMatrix"."ExpiryDate") = EXTRACT(YEAR FROM current_date);

因此,原始的 SQL 语句将是:

SELECT * FROM (SELECT DISTINCT ON ("TrainingMatrix".payroll, "TrainingName", "Institute")"gendata"."Employee Name","gendata"."Position", "gendata"."Department",  "TrainingMatrix".* 
FROM "TrainingMatrix" JOIN "gendata" ON "TrainingMatrix".payroll = "gendata".payroll 
ORDER  BY payroll, "TrainingName", "Institute" ,"TrainingDate" DESC NULLS LAST) AS foo WHERE "TrainingMatrix"."ExpiryDate" - current_date <= 0 
AND  EXTRACT(YEAR FROM  "TrainingMatrix"."ExpiryDate") = EXTRACT(YEAR FROM current_date);

但是我收到了这个错误:

错误:缺少表“TrainingMatrix”第 3 行的 FROM 子句条目: ...te" ,"TrainingDate" DESC NULLS LAST) AS foo WHERE "TrainingM...

我正在使用 PostgreSQL。大家有什么建议吗?

sql database postgresql greatest-n-per-group
3个回答
9
投票

100% @a_horse 已经说过了。另外还有一些事情:

  • 格式化您的查询,以便在尝试调试之前易于人们阅读和理解。更重要的是,在您在公共论坛上发帖之前。

  • 使用

    表别名,尤其是使用不幸的 CaMeL 大小写名称,以使其更易于阅读。

  • 在查询中提供您的表定义或至少

    table-qualify列名称,以便我们有机会解析它。您眼前的问题已在下面的查询中得到解决。您还可以相应地替换 ?.

    • t
       .. 
      "TrainingMatrix"
      的别名
      
    • g
       .. 
      gendata
      的别名
      

SELECT * FROM ( SELECT DISTINCT ON (t.payroll, ?."TrainingName", ?."Institute") g."Employee Name", g."Position", g."Department", t.* FROM "TrainingMatrix" t JOIN gendata g ON g.payroll = t.payroll ORDER BY t.payroll, ?."TrainingName", ?."Institute" , ?."TrainingDate" DESC NULLS LAST ) AS foo WHERE foo."ExpiryDate" - current_date <= 0 AND EXTRACT(YEAR FROM foo."ExpiryDate") = EXTRACT(YEAR FROM current_date);

但还有更多。

  • 就像 @a_horse 所写的那样,使用必须始终用双引号引起来的非法标识符是一个坏主意。但是带有封闭空间

    字符的标识符更糟糕:"Employee Name"

    。这距离自制 SQL 注入仅一步之遥。

  • 附加过滤器的措辞方式

    对性能不利

    WHERE "ExpiryDate" - current_date <= 0
    
    
    不是

    sargable,因此不能使用普通索引。撇开这一点不谈,它的成本也比实际需要的要高。代替使用:

    WHERE "ExpiryDate" >= current_date
    
    
    与第二个表达式类似,应重写为:

    WHERE "ExpiryDate" >= date_trunc('year', current_date) AND "ExpiryDate" < date_trunc('year', current_date) + interval '1 year'
    
    
    将两者结合起来,我们可以去掉多余的表达式:

    WHERE "ExpiryDate" >= current_date AND "ExpiryDate" < date_trunc('year', current_date) + interval '1 year'
    
    
  • 你的问题

    含糊不清。您想在 DISTINCT

     之前还是之后应用附加过滤器?不同的结果。
    假设
    before DISTINCT
    ,您不需要子查询 - 这消除了直接问题的原因:子查询没有不同的别名。

大家一起:

SELECT DISTINCT ON (t.payroll, "TrainingName", "Institute") g."Employee Name", g."Position", g."Department", t.* FROM "TrainingMatrix" t JOIN gendata g USING (payroll) WHERE t."ExpiryDate" >= current_date AND t."ExpiryDate" < date_trunc('year', current_date) + interval '1 year' ORDER BY t.payroll, "TrainingName", "Institute", "TrainingDate" DESC NULLS LAST
    

6
投票
当您将实际查询包装到派生表(

select .. from (...) as foo

)中时,您的“表”不再被称为
TrainingMatrix
。您需要使用派生表使用的别名来引用它:

select * from ( ... you original query .. ) as foo where foo."ExpiryDate" - current_date <= 0 and extract(year from foo."ExpiryDate") = extract(year from current_date)


顺便说一句:我建议您停止使用带引号的标识符

"ExpiryDate"

,使用区分大小写的名称通常会给您带来更多的麻烦。 


0
投票
我创建了

person

 表,然后在其中插入了 2 行,如下所示:

CREATE TABLE person ( id INTEGER, name VARCHAR(20), age INTEGER ); INSERT INTO person (id, first_name, last_name, age) VALUES (1, 'John', 27), (2, 'David', 32);
然后,尝试使用 

SELECT 语句

获取 
person 表,省略 FROM
 子句会得到相同的错误,如下所示:

postgres=# SELECT person.id, person.name, person.age; ERROR: missing FROM-clause entry for table "person" LINE 1: SELECT person.id, person.name, person.age;
但是,我可以得到带有 

person

 语句和 
SELECT
 子句的 
FROM
 表,如下所示:

postgres=# SELECT person.id, person.name, person.age FROM person; id | name | age ----+-------+----- 1 | John | 27 2 | David | 32 (2 rows)
    
© www.soinside.com 2019 - 2024. All rights reserved.