First of all, you don't need a plpgsql function for that. A plain query does the job. A CTE helps in this case:
WITH x AS (
SELECT uid, count(*) as ct
FROM hascooked
GROUP BY uid
)
SELECT count(*) AS cooks_with_fewer_recipies
FROM x
WHERE ct < (SELECT ct FROM x WHERE uid = u);
Next, an number of things is wrong with this statement:
select distinct uid,count(uid) as "sum" into uidSum from HasCooked group by uid;
These points are just my advice, not strictly wrong:
You already GROUP BY uid, a DISTINCT is pointless in this particular case.
Don't use the name of a function (sum) as column name. Only leads to problems.
With a proper name, you don't need double quotes ("sum"). Just my advice, not strictly wrong.
You can use mixed case identifiers, but don't. Identifiers are folded to lower case if not double-quoted. Read about identifiers in the manual.
As you GROUP BY uid, it is better to use count(*) instead of count(uid). Slightly faster, and better results in the (unlikely?) case that uid could be NULL - then you get a count for the NULL- cases, too.
Cleaned up form (still wrong!):
SELECT uid, count(*) as ct INTO uidSum
FROM hascooked
GROUP BY uid;
The statement is still wrong, because you try to assign multiple rows to the single variable uidSum, which is not possible.
A record can hold multiple columns, not multiple rows. You need a table for that or aggregate the rows into one.
Only the first row will be assigned, which is picked at random as you have no ORDER BY. DISTINCT used to guarantee that the result set is ordered by the DISTINCT columns, but this is not true any more since version 8.4. I quote the release notes for 8.4
SELECT DISTINCT and UNION/INTERSECT/EXCEPT no longer always produce
sorted output (Tom)
In any case, ordering by uid is as nonsensical as retrieving a single row in this context. It is obviously not what you want. One other way would be to loop through the resulting rows, one by one. More about loops here.
The proper solution is my query above.
uidSumis a record of. Use the simple variables,uSumandranking, in the INTO clause:INTO uSum, ranking. There's a very good chance that will work. (I simply don't know about the record notation in PostgreSQL, which is one reason this is a comment rather than an answer.)RETURN ranking;somewhere.