Postgres, получить уникальные записи в день от выбранного диапазона дат - PullRequest
0 голосов
/ 16 января 2019

Мне нужно сделать отчет с зарегистрированными пользователями по диапазону дат, но без дубликатов в один и тот же день (если кто-то был зарегистрирован дважды в один и тот же день, мы не будем перечислять его дважды). к сожалению, мы храним информацию для входа в систему как json (да, я не могу изменить ее на отдельную таблицу, я не знаю, кто разработал эту базу данных). Запрос на просмотр всех зарегистрированных пользователей:

select a.id, username, email, ah.modified as login_date
from accounts a join
     account_history ah
     on modified_acc_id = a.id
 where ah.data::jsonb->>'message' = 'Logon';

Изменена метка времени с часовым поясом, и она используется в качестве даты входа.

Я нашел только примеры с количеством различных идентификаторов в день, но я не знаю, как изменить его, чтобы он возвращал разные результаты в день

пример данных:

 id  |        username  |              email       |         login_date
-----+-------------------------+---------------------------------+----------------------------
 102 | example          | example@example.com      | 2018-12-06 09:30:10.573+00
 102 | example          | example@example.com      | 2018-12-06 09:32:34.235+00
  42 | rafal            | rafal@example.com        | 2018-12-06 09:45:24.884+00
 576 | john             | john@example.com         | 2018-12-06 09:35:24.922+00
 576 | john             | john@example.com         | 2018-12-07 09:58:04.253+00

требуемые данные:

 id  |        username  |              email       |         login_date
-----+-------------------------+---------------------------------+----------------------------
 102 | example          | example@example.com      | 2018-12-06 09:30:10.573+00
  42 | rafal            | rafal@example.com        | 2018-12-06 09:45:24.884+00
 576 | john             | john@example.com         | 2018-12-06 09:35:24.922+00
 576 | john             | john@example.com         | 2018-12-07 09:58:04.253+00

Так что, как видите, без второго ряда

Ответы [ 4 ]

0 голосов
/ 16 января 2019

Кажется, что когда происходит дурак, вы берете самое раннее свидание. Если это так, это работает?

select
  a.id, username, email, min (ah.modified) as login_date
from accounts a join
     account_history ah
     on modified_acc_id = a.id
 where ah.data::jsonb->>'message' = 'Logon'
group by a.id, username, email, ah.modified::date
0 голосов
/ 16 января 2019

использовать оконную функцию row_number()

select id,username,email,login_date from 
(
 select a.id, username, email, ah.modified as login_date,
row_number() over(partition by a.id, username,email order by ah.modified) rn
 from accounts a join
 account_history ah
 on modified_acc_id = a.id
 where ah.data::jsonb->>'message' = 'Logon'
) t where t.rn=1
0 голосов
/ 16 января 2019

DISTINCT ON дает вам точно первый ряд упорядоченной группы. В вашем примере группа представляет собой id и date часть login_date отметки времени

SELECT DISTINCT ON (id, login_date::date)
    *
FROM (
    -- <your query>
) s
ORDER BY id, login_date::date, login_date

демо: дб <> скрипка

Объяснение предложения ORDER BY:

Сначала вы должны сделать заказ по столбцам DISTINCT. Но в вашем случае вы не хотите заказывать только по дате, но и по времени. Таким образом, после упорядочения по дате (что необходимо из-за ваших столбцов DISTINCT), вы также должны упорядочить по отметке времени.


Таким образом, весь запрос может быть упрощен до (без подзапроса):

SELECT DISTINCT ON (a.id, ah.modified::date) 
    a.id, 
    username, 
    email, 
    ah.modified as login_date
FROM accounts a 
JOIN account_history ah
    ON modified_acc_id = a.id
WHERE ah.data::jsonb->>'message' = 'Logon'
ORDER BY a.id, ah.modified::date, ah.modified 
0 голосов
/ 16 января 2019

Похоже, вам нужно количество дней для определенного периода времени. Если я правильно понимаю:

select count(*) as num_user_days_in_range
from (select a.username, date_trunc('day', ah.modified) as login_date
      from accounts a join
           account_history ah
           on modified_acc_id = a.id
      where ah.data::jsonb->>'message' = 'Logon'
      group by a.username, login_date
     ) u
where login_date >= $date1 and login_date < $date2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...