Получить текущие / самые старые значения из таблицы для каждого клиента на основе дат? - PullRequest
0 голосов
/ 31 января 2020

У меня есть таблица, которая отслеживает имена клиентов, в каком штате США они живут и когда они туда переехали. Вот пример кода для его создания:

DECLARE @Customers TABLE (Customer_Name VARCHAR(20), Residence_State VARCHAR(20), Move_In_Date DATE)

INSERT INTO @Customers VALUES
('Rachel', 'Wisconsin', '2010-01-01'),
('Rachel', 'Nevada', '2012-06-03'),
('Rachel', 'Arizona', '2018-02-01'),
('Chad', 'Texas', '2010-01-01'),
('Chad', 'Idaho', '2012-04-15'),
('Chad', 'Texas', '2019-11-17'),
('Jake', 'Illinois', '2010-01-01'),
('Jake', 'Florida', '2011-02-04'),
('Jake', 'Wisconsin', '2013-08-13'),
('Jake', 'California', '2016-01-15')

Учитывая эту таблицу, я хотел бы получить строку для каждого клиента, в которой указано его имя, его старейшее известное государство проживания и текущее состояние проживания. Таким образом, для приведенных выше данных это будет:

Rachel - Wisconsin - Arizona
Chad - Texas - Texas
Jake - Illinois - California

Какой самый эффективный способ написать этот запрос?

Ответы [ 2 ]

2 голосов
/ 31 января 2020

Ваш код выглядит как SQL Сервер. К сожалению, функции агрегации first() нет. Но вы можете использовать first_value():

select distinct customer_name,
       first_value(residence_state) over (partition by customer_name order by move_in_date) as first_residence_state,
       first_value(residence_state) over (partition by customer_name order by move_in_date desc) as last_residence_state
from @customers c;

Здесь - это дБ <> скрипка.

0 голосов
/ 31 января 2020

Вы также можете сделать это row_number() и условное агрегирование:

select
    customer_name,
    max(case when rn_asc = 1 then residence_state end) first_residence_state,
    max(case when rn_desc = 1 then residence_state end) last_residence_state
from (
    select 
        c.*,
        row_number() over(partition by customer_name order by move_in_date asc) rn_asc,
        row_number() over(partition by customer_name order by move_in_date desc) rn_desc
    from @customers c
) c
where 1 in (rn_asc, rn_desc)
group by customer_name

Внутренний запрос ранжирует записи каждого customer_name по возрастанию и убыванию move_in_date. Затем внешний запрос агрегирует по customer_name и использует условные выражения для извлечения residence_state, которые соответствуют первому и последнему move_in_date каждого клиента.

Демонстрация в БД Скрипка :

customer_name | first_residence_state | last_residence_state
:------------ | :-------------------- | :-------------------
Chad          | Texas                 | Texas               
Jake          | Illinois              | California          
Rachel        | Wisconsin             | Arizona             
...