Выбор текущей действительной записи исторических данных с помощью SQL - PullRequest
0 голосов
/ 05 мая 2020

У меня есть 2 таблицы

Таблица Customer

  • customer_shortcut (char)

Таблица CustomerData

  • customerID ( ForeignKey для клиента)
  • customer_valid (Действительная дата для записи)
  • customer_name (char)

Таблица CustomerData может иметь несколько записей для клиента, но с разными действительные даты, pe

01.01.2019
01.01.2020
01.01.2021

Мне удалось получить последнюю запись для каждого клиента, используя запрос:

SELECT Customer.*
FROM Customer
    FULL JOIN CustomerData ON (Customer.id = CustomerData."customerID_id")
    FULL JOIN CustomerData CustomerData2 ON (Customer.id = CustomerData2."customerID_id" 
        AND (CustomerData.customer_valid < CustomerData2.customer_valid 
             OR CustomerData.customer_valid = CustomerData2.customer_valid 
             AND CustomerData.id < CustomerData2.id)
            )
WHERE CustomerData2.id IS NULL

Как мне теперь получить текущую действительную запись (в моем примере запись с customer_valid 01.01.2020)?

Я пытался добавить "AND customer_valid <= '2020-05-05' почти к каждой позиции в запросе, но так и не получил ожидаемого результата. </p>

1 Ответ

1 голос
/ 05 мая 2020

Если я правильно вас понял, вы ищете самую высокую «действительную дату», которая предшествует «сегодняшнему дню» (или любой заданной дате). Это может быть достигнуто с помощью бокового соединения в Postgres:

SELECT c.*, cd.customer_name
FROM customer c
  JOIN LATERAL (
    SELECT * 
    FROM customerdata cd 
    WHERE c.id = cd.customer_id
      AND cd.customer_valid <= current_date
    ORDER BY cd.customer_valid DESC 
    LIMIT 1
  ) cd on true

Более эффективным вариантом будет (на мой взгляд) сохранение начала и конца допустимого периода в daterange столбец :

create table customer_data
(
  customer_id    int not null references customer, 
  valid_during   daterange not null,
  customer_name  text
);

Перекрывающиеся диапазоны можно предотвратить с помощью ограничения исключения

И примеры диапазонов из вашего вопроса будут сохранены как

[2019-01-01,2020-01-01)
[2020-01-01,2021-01-01)
[2021-01-01,infinity)

) означает, что правый край исключен.

Запрос становится таким простым, как:

SELECT c.*, cd.customer_name
FROM customer c
  JOIN customer_data cd 
    on c.id = cd.customer_id
   AND cd.valid_during @> current_date;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...