Выберите строки из объединенных таблиц с более чем n вхождений - PullRequest
0 голосов
/ 05 июля 2018

Моя проблема похожа на MySQL: выберите строки с более чем одним вхождением , но я использую PostgreSQL. У меня есть запрос как:

select d.user_id, d.recorded_at, d.glucose_value, d.unit
from diary as d
join (
    select u.id
    from health_user as u
    join (
        select distinct user_id
        from care_connect
        where clinic_id = 217
            and role = 'user'
            and status = 'active'
    ) as c
    on u.id = c.user_id
    where u.is_tester is false
) as cu
on d.user_id = cu.id
where d.created_at >= d.recorded_at
    and d.recorded_at < current_date and d.recorded_at >= current_date - interval '30 days'
    and d.glucose_value > 0
    and (d.state = 'wakeup' or (d.state = 'before_meal' and d.meal_type = 'breakfast'))

Результат выглядит так:

+---------+---------------------+---------------+--------+
| user_id |     recorded_at     | glucose_value |  unit  |
+---------+---------------------+---------------+--------+
|   12041 | 2018-06-26 01:10:12 |           100 | mg/dL  |
|   12041 | 2018-06-30 02:10:11 |            90 | mg/dL  |
|   12214 | 2018-06-25 12:40:13 |            10 | mmol/L |
|   12214 | 2018-06-26 12:41:13 |            12 | mmol/L |
|   12214 | 2018-06-29 00:21:14 |            11 | mmol/L |
|   12214 | 2018-06-29 12:59:32 |            10 | mmol/L |
+---------+---------------------+---------------+--------+

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

select d.user_id, d.recorded_at, d.glucose_value, d.unit, count(d.*)
from diary as d
join (
    select u.id
    from health_user as u
    join (
        select distinct user_id
        from care_connect
        where clinic_id = 217
            and role = 'user'
            and status = 'active'
    ) as c
    on u.id = c.user_id
    where u.is_tester is false
) as cu
on d.user_id = cu.id
where d.created_at >= d.recorded_at
    and d.recorded_at < current_date and d.recorded_at >= current_date - interval '30 days'
    and d.glucose_value > 0
    and (d.state = 'wakeup' or (d.state = 'before_meal' and d.meal_type = 'breakfast'))
group by d.user_id
having count(d.*) >= 4

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

+---------+---------------------+---------------+--------+
| user_id |     recorded_at     | glucose_value |  unit  |
+---------+---------------------+---------------+--------+
|   12214 | 2018-06-25 12:40:13 |            10 | mmol/L |
|   12214 | 2018-06-26 12:41:13 |            12 | mmol/L |
|   12214 | 2018-06-29 00:21:14 |            11 | mmol/L |
|   12214 | 2018-06-29 12:59:32 |            10 | mmol/L |
+---------+---------------------+---------------+--------+

Однако, он выдает ошибку, говоря, что d.recorded_at также должен быть добавлен в group by, но это не то, что я хочу. Кроме того, группировка необработанных временных меток не имеет смысла.

Я знаю, что, вероятно, могу присоединиться к другой таблице, которая генерируется по тому же запросу, но только select d.user_id, count(d.*) в первой строке, но весь запрос выглядел бы сумасшедшим.

Кто-нибудь, пожалуйста, помогите мне, как добиться этого лучше? Извините, я не помещаю здесь структуры таблиц, но я могу редактировать и уточнять вещи, если это необходимо.

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Попробуйте это:

Замените your_query вашим фактическим запросом.

Использование с предложением и существует предложение .

with original_query as ( your_query )
select * from original_query q1
where 
exists( select q2.user_id from original_query q2 where q1.user_id = q2.user_id
group by q2.user_id 
having count(q2.user_id) >= 4 )
0 голосов
/ 05 июля 2018

Попробуйте это

Select user_id, recorded_at, glucose_value, unit
From (
select d.user_id, d.recorded_at, d.glucose_value, d.unit, count(1) over (partition by d.user_id) rcnt
from diary as d
join (
    select u.id
    from health_user as u
    join (
        select distinct user_id
        from care_connect
        where clinic_id = 217
            and role = 'user'
            and status = 'active'
    ) as c
    on u.id = c.user_id
    where u.is_tester is false
) as cu
on d.user_id = cu.id
where d.created_at >= d.recorded_at
    and d.recorded_at < current_date and d.recorded_at >= current_date - interval '30 days'
    and d.glucose_value > 0
    and (d.state = 'wakeup' or (d.state = 'before_meal' and d.meal_type = 'breakfast'))
) x 
Where rcnt >= 4
...