[英]Missing FROM-clause entry for a table
我编写了以下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);
但我得到了这个错误:
错误:缺少FROM“子句条目表”TrainingMatrix“第3行:...... te”,“TrainingDate”DESC NULLS LAST)AS foo WHERE“TrainingM ...
我正在使用PostgreSQL。 任何建议家伙?
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);
但还有更多。
就像@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
之前或之后应用其他过滤器? 结果不同。
假设在 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
当您将实际查询包装到派生表( 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"
使用区分大小写的名称通常会给你带来更多的麻烦。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.