PostgreSQL列必须通过子句出现在组中,或在汇总函数中使用。当在子句中使用案例表达式在订单中
我获得列“ MeadurementResults.value”必须通过子句出现在组中,或在汇总函数中使用此查询的错误
错误:
SELECT avg("measurementResults"."value") AS "value",
min("measurement"."timestamp") AS "timestamp",
min("testProtocolItemResults"."ranking") AS "ranking"
FROM "measurement"
JOIN "measurementResults" ON "measurementResults"."measurement" = "measurement"."id"
JOIN "conditions" ON "conditions"."measurement" = "measurement"."id"
JOIN "testProtocolItemResults" ON "testProtocolItemResults"."id" = "measurementResults"."testProtocolItemResults"
JOIN "testProtocolSessionItem" ON "testProtocolSessionItem"."id" = "measurement"."testProtocolSessionItem"
WHERE "measurement"."athlete" = 334
AND "measurementResults"."testProtocolItemResults" = 1
AND "conditions"."conditions" = '6'
GROUP BY "testProtocolSessionItem"."testProtocolSession",
"testProtocolItemResults"."ranking"
ORDER BY (CASE
WHEN "ranking" = 'greater'::text THEN "value"
ELSE NULL::double precision
END) DESC
LIMIT 3
如果我通过这样的子句更改订单,则可以按预期工作:
...
ORDER BY "value" DESC
...
我在做什么错?
I get the column "measurementResults.value" must appear in the GROUP BY clause or be used in an aggregate function
error for this query:
SELECT avg("measurementResults"."value") AS "value",
min("measurement"."timestamp") AS "timestamp",
min("testProtocolItemResults"."ranking") AS "ranking"
FROM "measurement"
JOIN "measurementResults" ON "measurementResults"."measurement" = "measurement"."id"
JOIN "conditions" ON "conditions"."measurement" = "measurement"."id"
JOIN "testProtocolItemResults" ON "testProtocolItemResults"."id" = "measurementResults"."testProtocolItemResults"
JOIN "testProtocolSessionItem" ON "testProtocolSessionItem"."id" = "measurement"."testProtocolSessionItem"
WHERE "measurement"."athlete" = 334
AND "measurementResults"."testProtocolItemResults" = 1
AND "conditions"."conditions" = '6'
GROUP BY "testProtocolSessionItem"."testProtocolSession",
"testProtocolItemResults"."ranking"
ORDER BY (CASE
WHEN "ranking" = 'greater'::text THEN "value"
ELSE NULL::double precision
END) DESC
LIMIT 3
If I change the ORDER BY clause like this, it works as expected:
...
ORDER BY "value" DESC
...
What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的问题有几个根源:
最重要的是,不要将相同名称用于与输入列不同(同名)不同的输出列。那是一个装满的脚枪。
其次,将其养成表格质量的习惯列中,用于复杂查询中的涉及多个表。即使这似乎有效,它也可能已经在做其他事情。即使它正常工作,如果更改了任何列名(添加,删除),它也可能会破裂。运气不好,它默默地破裂了,您的疑问是胡说八道后的疑问。
第三,SQL标准有一些令人困惑的可见性规则。 :
请参阅 “ value” 解决输出列
“ value”
,它隐藏了 订单中同名的任何输入列。这是按预期工作的(也就是说,如果您实际上是要针对输出列)。在您的失败查询中,
“ value”
解决到输入列“ MeadurementResults.Value”
。您不能将输出列通过 以顺序进行新的计算,您只能使用“按原样”使用它们。因此,随着输出列的范围,
“ value”
可以解决到输入列(现在不再隐藏)。这导致报告的错误。显然,汇总后您不能通过输入列订购 - 除非您直接或间接地通过它进行分组。您可以通过:
所有行
排名='更大'
不正确的所有行 - 就像您的case
表达式一样。因此,处理null
和false
都一样。微妙的差异:那些领先的行被
value
排序,而您的原始行将按任意顺序列出它们。可能会或可能不欢迎。我假设您知道
null
值以降序排序排序吗?你可以改变吗?请参阅:如果这还不够好(或为更复杂的表达式),您必须更详细且明确:一种方法是将整个查询包装到一个子查询中,然后在Outer
中订购(和限制!)选择
:尤其是对于具有小
limit限制
的查询,如果Postgres无法再优化查询计划,这可能会更昂贵。一边:
使用 Legal,Loser-Case标识符,因此您不必双引号。
并使用
Your problem has a couple of roots:
Most importantly, don't use the same name for an output column that is distinct from an input column (of the same name). That's a loaded foot-gun.
Secondly, make it a habit to table-qualify all columns used in a complex query involving multiple tables. Even if that seems to work, it might already be doing something else than you think. And even if it works correctly it may break later, if any column names are changed (added, removed renamed). With some bad luck it breaks silently, and your query happily ever after produces nonsense.
Thirdly, the SQL standard, which has somewhat confusing visibility rules. See:
In your working alternative query,
"value"
resolves to the output column"value"
, which hides any input column of the same name inORDER BY
. That works as expected (that is, if you actually meant to target the output column).In your failing query,
"value"
resolves to the input column"measurementResults.value"
. You cannot throw output columns into a new computation inORDER BY
, you can only use them "as is". So, with output columns out of the way,"value"
resolves to the input column (now not hidden any more). And that leads to the reported error. Obviously, you cannot order by an input column after aggregating - except if you grouped by it, directly or indirectly.You could repair your query with:
The sorts all rows where
ranking = 'greater'
is not true to the top - like yourCASE
expression would. So treatingnull
andfalse
alike.Subtle difference: Those leading rows are sorted by
value
, while your original would list them in arbitrary order. May or may not be welcome.I assume you are aware that
null
values sort on top in descending order? And that you can change that? See:If that's not good enough (or for more complex expressions), you must be more verbose and explicit: one way is to wrap the whole query into a subquery, and order (and limit!) in the outer
SELECT
:Especially for queries with a small
LIMIT
, this may be more expensive if Postgres cannot optimize the query plan as well any more.Aside:
Use legal, loser-case identifiers, so you don't have to double-quote.
And use table aliases to de-noise your big queries.