Как объединить таблицы с неравным условием? - PullRequest
1 голос
/ 27 апреля 2019

Я пытаюсь запросить всех пользователей с их первой успешной установкой приложения с подробностями версии приложения.

Поэтому я попытался запросить у пользователя первую успешную установку, а затем сравнить установленную дату с последней версией приложения до установленной даты.

SELECT DISTINCT user_id, installed_time
WHERE state=SUCCESSFUL
FROM installation
ORDER BY ASC

Приведенный выше запрос возвращает всех пользователей с их первой успешной установкой.

Как узнать, какую версию приложения они установили при первой успешной установке?

Мои таблицы описаны ниже:

Installation:
user_id,
installed_date,

Version:
version_id,
release_date,
release_code,

Ответы [ 3 ]

1 голос
/ 27 апреля 2019

Я не верю, что этот запрос делает то, что вы говорите:

SELECT DISTINCT user_id, installed_time
WHERE state=SUCCESSFUL
FROM installation
ORDER BY ASC;

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

Я думаю, что запрос должен быть:

SELECT i.user_id, MIN(i.installed_time)
FROM installation i
WHERE i.state = 'SUCCESSFUL'
GROUP BY i.user_id;

Или, если вы хотите, чтобы все столбцы в таблице, использовали DISTINCT ON:

SELECT DISTINCT ON (i.user_id) i.*
FROM installation i
WHERE i.state = 'SUCCESSFUL'
ORDER BY i.user_id, i.installation_time

Если вам нужна действительная версия в то время, у вас есть несколько вариантов. В Postgres я бы рекомендовал боковое соединение:

SELECT i.*, v.*
FROM (SELECT i.user_id, MIN(i.installed_time) as installed_time
      FROM installation i
      WHERE i.state = 'SUCCESSFUL'
      GROUP BY i.user_id
     ) i LEFT JOIN LATERAL
     (SELECT v.*
      FROM versions v
      WHERE v.release_date <= i.installed_time
      ORDER BY v.release_date DESC
      FETCH FIRST 1 ROW ONLY
     ) v
     ON 1=1;
0 голосов
/ 27 апреля 2019

Вы можете использовать distinct on (...) с order by, чтобы получить версию самой ранней установки.Выражение distinct on должно соответствовать крайнему левому выражению order by.

select  distinct on (i.user_id)
,       i.user_id
,       i.installed_date 
,       v.release_code
from    installation i
join    version v
on      v.release_date <= i.installed_date
where   i.state = 'SUCCESSFUL'
order by
        i.user_id              -- Required for distinct on, see note above
,       i.installed_date desc  -- First installation per user
,       v.release_date         -- Latest version available at installation date
0 голосов
/ 27 апреля 2019

Вы можете легко достичь этого, используя window-functions . Оконные функции чрезвычайно полезны для «продвинутых» скриптов SQL.

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

SELECT DISTINCT
  i.user_id,
  FIRST_VALUE(v.version_id) OVER(
    PARTITION BY i.user_id
    ORDER BY v.released_date DESC
  ) AS first_version_installed
FROM installation AS i
INNER JOIN version AS v
  ON i.installation_date >= v.released_date
WHERE i.state = 'SUCCESSFULL'

Дополнительная литература:

...