This is a strange test case from the Postgres regression test suite.
It starts with a table named tenk
, which has 10,000 rows in it. The table has a column called unique1
, both of which contain values from 0 to 9999, each row in the table having a unique value for that column for each column. (ie. one row has 369 for unique1
and 6521 for unique2
, and no other row has those values, though there’s a row that has 369 for unique2
and a row that has 6521 for unique1
.)
The test query is:
select
(select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1)))
from tenk1 o;
This returns a single row with a value of 9999
. And that feels odd. Here’s how I parse the query in my own head:
Select [subquery] from tenk1 o
Subquery selects max(i.unique2) from tenki, where i.unique1 = o.unique1
This is basically a really weird way to write a self-join.
For each row in o, select the max i.unique2 value that corresponds to it.
There are 10,000 rows in o, each will have exactly 1 match in i.
Return 10,000 rows in the result set.
Where am I getting this wrong?
EDIT: The behavior is even stranger when you change the code around a little.
The SELECT seems to be equivalent to a join between tables i
and o
, but if you rewrite it as one:
select
(select max((select i.unique2 from tenk1 i join tenk1 o on i.unique1 = o.unique1)))
it errors out:
ERROR: more than one row returned by a subquery used as an expression
But if you instead remove the max
from the original query,
select
(select (select i.unique2 from tenk1 i where i.unique1 = o.unique1))
from tenk1 o;
you get a result set of 10,000 elements, as expected. The database seems to have no trouble with a subquery returning more than one row here! Remove the table o
from that inexplicably valid query,
select
(select (select i.unique2 from tenk1 i))
and the "more than one row" error returns!
This is official PostgreSQL behavior, that the test suite requires the database to uphold. The rule set forth by the error message says you can’t have a subquery used as an expression that returns more than one row. What it it about this strange not-quite-join to a table in an external scope that circumvents this rule?
2
Answers
would do what you said, but the query doesn’t do that. It does an inner
(which is, as you say, a weird, even pointless, self-join, but this is a test case). That produces one row per row of the "outer"
tenk1
. Then it it usesmax
to get the single largest value ofunique2
that came out of the query (which is also the largest value in the table).It is test for a regression.
Per aggregrate.sql:
Where bug report is aggregate over subselects fails:
Patch is Aggregrate patch:
With the aggregates.sql (r1.13.4.1 -> r1.13.4.2) patch being: