Re: Adding AVG to a JOIN - Mailing list pgsql-general

From Alexander Farber
Subject Re: Adding AVG to a JOIN
Date
Msg-id CAADeyWinFoZkO3FzRDFyvyTbdqCdu11OkDTtzC8McAfJErjU0A@mail.gmail.com
Whole thread Raw
In response to Re: Adding AVG to a JOIN  (Alexander Farber <alexander.farber@gmail.com>)
Responses Re: Adding AVG to a JOIN
List pgsql-general
Good evening,

On Mon, Apr 23, 2018 at 12:56 PM, Alexander Farber <alexander.farber@gmail.com> wrote:
On Mon, Apr 23, 2018 at 12:15 PM, Daniel Verite <daniel@manitou-mail.org> wrote:

You may use a correlated subquery in the SELECT clause,

               SELECT
                        u.elo,
                        (SELECT ROUND(AVG(score), 1) FROM words_moves WHERE uid = u.uid) AS score,
                        s.given,
                        s.photo
                FROM words_users u
                JOIN words_social s USING (uid)
                WHERE u.elo > 1500
                -- take the most recent record from words_social
                AND NOT EXISTS (SELECT 1
                                FROM words_social x
                                WHERE s.uid = x.uid
                                AND x.stamp > s.stamp)
                -- only show players who where active in the last week
                AND EXISTS (SELECT 1
                            FROM words_moves
                            WHERE played > CURRENT_TIMESTAMP - INTERVAL '1 week'
                            AND action IN ('play', 'skip', 'swap', 'resign'))
                ORDER BY u.elo DESC
                LIMIT 10


thank you all for helping me in adding an average score per move to my SQL JOIN.

Of course I would like to add yet another statistic and now am trying to add the average time per move to the same query, by prepending it a CTE with LAG():

                 WITH cte AS (
                        SELECT
                                m.gid,
                                m.uid,
                                m.played,
                                LAG(m.played) OVER (PARTITION BY m.gid ORDER BY played) AS prev_played
                        FROM words_moves m
                        JOIN words_games g ON (m.gid = g.gid AND m.uid in (g.player1, g.player2))
                        WHERE m.played > CURRENT_TIMESTAMP - interval '1 month'
                ) 
                SELECT
                        u.elo,
                        AVG(c.played - c.prev_played) AS avg_time_per_move,
                        (SELECT ROUND(AVG(score), 1) FROM words_moves WHERE uid = u.uid) AS score,
                        s.given,
                        s.photo
                FROM words_users u 
                JOIN words_social s USING (uid)
                JOIN cte c USING (uid)
                WHERE u.elo > 1500 
                -- take the most recent record from words_social
                AND NOT EXISTS (SELECT 1 
                                FROM words_social x 
                                WHERE s.uid = x.uid 
                                AND x.stamp > s.stamp)
                -- only show players who where active in the last week
                AND EXISTS (SELECT 1
                            FROM words_moves
                            WHERE played > CURRENT_TIMESTAMP - INTERVAL '1 week'
                            AND action IN ('play', 'skip', 'swap', 'resign'))
                ORDER BY u.elo DESC
                LIMIT 10;

but this fails with 

ERROR:  42803: column "u.elo" must appear in the GROUP BY clause or be used in an aggregate function
LINE 15:                         u.elo,
                                 ^

And I don't understand why adding a CTE has caused it, because without the CTE the GROUP BY u.elo was not required...

Regards
Alex


pgsql-general by date:

Previous
From: Thomas Poty
Date:
Subject: Re: Using the public schema
Next
From: "David G. Johnston"
Date:
Subject: Re: Adding AVG to a JOIN