Как найти наименьшее значение без агрегатной функции в SQL? - PullRequest
0 голосов
/ 04 августа 2020

У меня есть этот пример набора данных на Postgres

 updated_at     activated_at        name     gender   role    school  app_name    device_type
-------------+-----------------+----------+--------+-------+---------+---------+---------------
August 2         July 30            Ron        M       S        A         Y          android
August 1         July 30            Ron        M       S        A         Z          browser
July 30          July 30            Ron        M       S        A         Y          android
August 1         July 28            Ana        F       S        B         Y          android
August 1         July 28            Ana        F       S        B         Z          browser
July 28          July 28            Ana        F       S        B         Y          android

Я хочу узнать, когда пользователь впервые показывает (updated_at) после его активированного_at и принадлежит какому приложению.

Ожидаемый результат:

 updated_at     activated_at        name     gender   role    school  app_name    device_type
-------------+-----------------+----------+--------+-------+---------+---------+---------------
July 30          July 30            Ron        M       S        A         Y          android
July 28          July 28            Ana        F       S        B         Y          android

Я пробовал это SQL:

SELECT min(ut.updated_at), u.activated_at, u.full_name, u.gender, r.name, s.name, ut.app_name, ut.device_type
FROM "public"."user_tokens" ut JOIN
     "public"."users" u
     ON ut.user_id = u.id JOIN
     "public"."user_roles" ur
     ON ut.user_id = ur.user_id JOIN
     "public"."roles" r
     ON ur.role_id = r.id JOIN
     "public"."schools" s
      ON ur.school_id = s.id
WHERE (NOT (ut.app_name) like 'G')
Group by u.activated_at, u.full_name, u.gender, r.name, s.name, ut.app_name, ut.device_type
Order by u.activated_at desc

Но результат похож на это:

 updated_at     activated_at        name     gender   role    school  app_name    device_type
-------------+-----------------+----------+--------+-------+---------+---------+---------------
August 1         July 30            Ron        M       S        A         Z          browser
July 30          July 30            Ron        M       S        A         Y          android
August 1         July 28            Ana        F       S        B         Z          browser
July 28          July 28            Ana        F       S        B         Y          android

Я пытался исключить app_name и device_type из предложения group by, но там написано: ERROR: column "ut.app_name" must appear in the GROUP BY clause or be used in an aggregate function

Есть идеи, как это решить? Любой вклад будет очень признателен. Спасибо.

Ответы [ 2 ]

2 голосов
/ 04 августа 2020

Я думаю, что DISTINCT ON, вероятно, лучший способ сделать это на Postgres:

SELECT DISTINCT ON (u.full_name)
    ut.updated_at,
    u.activated_at,
    u.full_name,
    u.gender,
    r.name,
    s.name,
    ut.app_name,
    ut.device_type
FROM "public"."user_tokens" ut
INNER JOIN "public"."users" u ON ut.user_id = u.id
INNER JOIN "public"."user_roles" ur ON ut.user_id = ur.user_id
INNER JOIN "public"."roles" r ON ur.role_id = r.id
INNER JOIN "public"."schools" s ON ur.school_id = s.id
WHERE NOT ut.app_name LIKE 'G'
ORDER BY
    u.full_name,
    ut.updated_at;

Приведенное выше вернет одну запись для каждого пользователя с полным именем, что соответствует более раннему updated_at времени .

0 голосов
/ 04 августа 2020

вы можете сначала отсортировать по возрастанию (от старого к новому) и использовать LIMIT для того, сколько записей вы хотите отобразить

select * from TABLE_NAME order by updated_at asc LIMIT 2;
...