PostgreSQL: GROUP BY clause or be used in an aggregate function

Всем привет.

Есть такой запрос,

SELECT
        global_user_id
        , os_family_1
    FROM (
        SELECT
            MD5(CONCAT(CASE WHEN bums.global_user_id::VARCHAR IS NULL THEN 'NULL'::VARCHAR ELSE bums.global_user_id::VARCHAR END)) AS global_user_id
            , dos.os_family_1 AS os_family_1
            , MAX(fpv.page_view_date) AS max_page_view_date
            , ROW_NUMBER() OVER (PARTITION BY bums.global_user_id ORDER BY fpv.page_view_date DESC) AS rn
        FROM "database"."data_warehouse__prod"."fact_page_views" AS fpv
        LEFT JOIN "database"."data_warehouse__prod"."dim_browser" AS dib ON dib.browser_key = fpv.browser_key
        LEFT JOIN "database"."data_warehouse__prod"."dim_os" AS dos ON dos.os_key = fpv.os_key
        LEFT JOIN "database"."data_warehouse__prod"."dim_page" AS dip ON dip.page_key = fpv.page_key
        LEFT JOIN "database"."data_warehouse__prod"."dim_snowplow_user" AS dsu ON dsu.snowplow_user_key = fpv.snowplow_user_key
        LEFT JOIN "database"."data_warehouse__prod"."outrigger_dim_site" AS ods ON ods.site_name = dip.page_app_id
        LEFT JOIN "database"."data_warehouse__prod"."bridge_user_model_snowplow" AS bums ON dsu.snowplow_user_key = bums.snowplow_user_key
        WHERE
            fpv.page_view_date::DATE >= (('2022-02-02'::DATE + -8 * INTERVAL '1 week'))
            AND fpv.page_view_date::DATE < (('2022-02-02'::DATE + 0 * INTERVAL '1 day'))
            AND (dib.is_a_bot) = 'This Is Not A Bot'
            AND (dib.is_internal_traffic) = 'This Is Not Internal Traffic'
            AND (ods.site_id IS NOT NULL)
        group by 1,2
        ) AS os_family_1
    WHERE rn = 1

но почему-то получаю ошибку.

column "fpv.page_view_date" must appear in the GROUP BY clause or be used in an aggregate function
LINE 18: ...) OVER (PARTITION BY bums.global_user_id ORDER BY fpv.page_v...

Сам не могу разобраться.


Ответы (1 шт):

Автор решения: Alexander Pavlov

Стоит указывать, какая задача решается.

Если "для каждого юзера найти OS, c которой он заходил в последний раз", то

SELECT
        global_user_id
        , os_family_1
    FROM (
        SELECT
            MD5(COALESCE(bums.global_user_id::VARCHAR, 'NULL')) AS global_user_id
            , dos.os_family_1 AS os_family_1
            , ROW_NUMBER() OVER (PARTITION BY bums.global_user_id ORDER BY fpv.page_view_date DESC) AS rn
        FROM "database"."data_warehouse__prod"."fact_page_views" AS fpv
        LEFT JOIN "database"."data_warehouse__prod"."dim_browser" AS dib ON dib.browser_key = fpv.browser_key
        LEFT JOIN "database"."data_warehouse__prod"."dim_os" AS dos ON dos.os_key = fpv.os_key
        LEFT JOIN "database"."data_warehouse__prod"."dim_page" AS dip ON dip.page_key = fpv.page_key
        LEFT JOIN "database"."data_warehouse__prod"."dim_snowplow_user" AS dsu ON dsu.snowplow_user_key = fpv.snowplow_user_key
        LEFT JOIN "database"."data_warehouse__prod"."outrigger_dim_site" AS ods ON ods.site_name = dip.page_app_id
        LEFT JOIN "database"."data_warehouse__prod"."bridge_user_model_snowplow" AS bums ON dsu.snowplow_user_key = bums.snowplow_user_key
        WHERE
            fpv.page_view_date::DATE >= (('2022-02-02'::DATE + -8 * INTERVAL '1 week'))
            AND fpv.page_view_date::DATE < (('2022-02-02'::DATE + 0 * INTERVAL '1 day'))
            AND (dib.is_a_bot) = 'This Is Not A Bot'
            AND (dib.is_internal_traffic) = 'This Is Not Internal Traffic'
            AND (ods.site_id IS NOT NULL)
        ) AS os_family_1
    WHERE rn = 1
→ Ссылка