Присоединяйтесь и считайте разные значения между 2 датами - PullRequest
1 голос
/ 01 октября 2019

У меня есть левая таблица:

CREATE TABLE tab (
  code int
, max  date
, min  date
);

И правая таблица с пользовательской активностью (одна строка на пользователя в день):

CREATE TABLE activity (
  date   date
, "user" text
);

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

Таблица tab (с добавленным столбцом, который я пытаюсь вычислить):

Code  Min          Max            (Expected output)
201   2019-1-8    2019-1-10           3
202   2019-1-8    2019-1-11           3
203   2019-1-11   2019-1-12           2

Таблица activity:

Date              User
2019-1-8         ABCD001
2019-1-8         ABCD002
2019-1-9         ABCD001
2019-1-9         ABCD003
2019-1-10        ABCD001
2019-1-11        ABCD002
2019-1-12        ABCD003

Я хочу выводить столбцы tab, расширенный числом отдельных пользователей activity в пределах этого диапазона дат

Так что мне нужно как-то присоединиться к диапазону дат от min до max.

Пробная версия 1:

select code, min, max, count(b.distinct user)
from tab a
left join activity b on b.date between a.min and a.max
group by 1,2,3 

Пробная версия 2:

select code, min, max, count(b.distinct user)
from tab a
left join activity b on b.date <= a.min and b.date >=a.max and b.date = a.min
group by 1,2,3

Я запустил разные версии вышеприведенного кода, но для его запуска требуются годы или он не работает.

1 Ответ

1 голос
/ 01 октября 2019

Я предлагаю LEFT JOIN LATERAL:

SELECT a.code, a.min, a.max, b.ct
FROM   tab a
LEFT   JOIN LATERAL (
   SELECT count(DISTINCT b."user") AS ct
   FROM   activity b
   WHERE  b.date BETWEEN a.min AND a.max
   ) b ON true;

Подобный запрос может быть дорогим, если диапазоны не малы. Каждый ряд слева включает ряд рядов справа. Кроме того, счет DISTINCT дорог для больших диапазонов. Но это должен быть самый быстрый запрос из возможных.

Поддержите его с index on activity(date, "user"). Добавляйте только 2-й индексный столбец, если вы получаете из него только индексные сканы.

user - это зарезервированное слово , кстати. Не используйте его в качестве идентификатора.
И я бы тоже не стал использовать date, min или max. Имена основных типов данных и функций в качестве идентификаторов могут привести к ошибкам.

Связано:

...