缺少表的FROM子句条目

Aan*_*Aan 7 sql database postgresql greatest-n-per-group

我编写了以下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;
Run Code Online (Sandbox Code Playgroud)

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

WHERE "TrainingMatrix"."ExpiryDate" - current_date <= 0 
AND  EXTRACT(YEAR FROM  "TrainingMatrix"."ExpiryDate") = EXTRACT(YEAR FROM current_date);
Run Code Online (Sandbox Code Playgroud)

因此,原始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);
Run Code Online (Sandbox Code Playgroud)

但我得到了这个错误:

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

我正在使用PostgreSQL.任何建议家伙?

Erw*_*ter 9

100%@a_horse已经说过了.还有几件事:

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

  • 使用表别名,尤其是使用不幸的CaMeL案例名称,以便于阅读.

  • 在查询中提供表定义或至少表限定列名,以便我们有机会解析它.您的直接问题已在下面的查询中修复.你也会相应地更换?.:

    • 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);
Run Code Online (Sandbox Code Playgroud)

但还有更多.

  • 就像@a_horse写的那样,使用必须一直双引号的非法标识符是个坏主意.但是封闭空格字符的标识符更糟糕:"Employee Name".这距离自制的SQL注入还有一步之遥.

  • 你的附加过滤器的措辞方式不利于性能.

    WHERE  "ExpiryDate" - current_date <= 0 
    
    Run Code Online (Sandbox Code Playgroud)

    不是sargable因此不能使用普通索引.抛开这一点,它也比它需要的更昂贵.改为使用:

    WHERE "ExpiryDate" >= current_date
    
    Run Code Online (Sandbox Code Playgroud)

    类似于你的第二个表达式,应该重写为:

    WHERE  "ExpiryDate" >= date_trunc('year', current_date)
    AND    "ExpiryDate"  < date_trunc('year', current_date) + interval '1 year'
    
    Run Code Online (Sandbox Code Playgroud)

    结合两者,我们可以删除冗余表达式:

    WHERE  "ExpiryDate" >= current_date
    AND    "ExpiryDate"  < date_trunc('year', current_date) + interval '1 year'
    
    Run Code Online (Sandbox Code Playgroud)
  • 你的问题很模糊.是否要在之前DISTINCT或之后应用其他过滤器?结果不同.
    假设之前 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
Run Code Online (Sandbox Code Playgroud)


a_h*_*ame 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)
Run Code Online (Sandbox Code Playgroud)

顺便说一句:我建议你停止使用引用的标识符,"ExpiryDate"使用区分大小写的名称通常会给你带来更多的麻烦.