Я хочу найти последнюю транзакцию для каждой учетной записи до определенной даты - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть таблица, которая определена (в SQL Server Azure) следующим образом:

CREATE TABLE dbo.[transaction] 
(
    id INT IDENTITY(1,1) NOT NULL,
    [date] DATETIME NULL,
    amount FLOAT NULL,
    balance FLOAT NULL,
    account_id INT NULL,
    CONSTRAINT PK__transact__32F PRIMARY KEY (id)
)

Я хочу найти последний баланс для каждой учетной записи до определенной даты.Мне нужно вернуть следующие столбцы: account_id, date, balance.

Я пробовал:

select account_id, max(date) as date 
from dbo.[transaction] 
group by account_id

Это работает, но баланс не возвращается.

Во-вторых, мои транзакции упорядочены сначала по дате, а затем по id.Поэтому, если в максимальную дату происходит несколько транзакций, следует выбрать баланс по транзакции с наибольшим идентификатором.

Мое приложение написано в flask-sqlalchemy, поэтому ответ sqlalchemy был бы отличным, но я также был бы рад ответу на SQL.

Ответы [ 3 ]

0 голосов
/ 20 декабря 2018

Решение: включая проверку даты

CREATE TABLE #transaction (
    id int NOT NULL,
    [date] datetime NULL,
    amount float NULL,
    balance float NULL,
    account_id int NULL
) ;

Insert Into #transaction Values
(1,'2018-11-20',50,4000,100),
(2,'2018-11-21',75,2475,100),
(3,'2018-12-15',75,2400,100),
(4,'2018-11-22',25,4000,200),
(5,'2018-11-22',25,4000,300)


With CTE As
(
   Select 
      ROW_NUMBER() Over(Partition By account_id Order By [Date] Desc) As rn,
      account_id, [Date], balance 
   From #transaction
   Where [Date] < '2018-12-01'
)
Select account_id, [Date], balance From CTE
Where  rn = 1 

Результат:

account_id  Date                    balance
100         2018-11-21 00:00:00.000 2475
200         2018-11-22 00:00:00.000 4000
300         2018-11-22 00:00:00.000 4000
0 голосов
/ 21 декабря 2018

Оба предоставленных ответа одинаково блестящие.

Я взял это и преобразовал его в ответ sqlalchemy на python для справки:

from sqlalchemy import func
from datetime import datetime
import pandas as pd

start = datetime(2018,12,1)

row_number_column = func.row_number()                                    \
        .over(partition_by=Transaction.account_id,
              order_by=(Transaction.date.desc(), Transaction.id.desc()))  \
        .label('row_number')

query = DB.session.query(
            Transaction.account_id,
            Transaction.date,
            Transaction.balance,
            row_number_column)                            \
        .filter(Transaction.date < start)                 \
        .from_self().filter(row_number_column == 1)

df = pd.DataFrame(query.all(), columns=['Account Id', 'Date', 'Balance', 'RowId'])
df.drop(['RowId'], axis=1, inplace=True)
print(df)

Последние три необязательные строки преобразуют это в кадр данных pandas с начальными сальдо, отсортированный по дате, а затемID.

0 голосов
/ 19 декабря 2018

Вы можете использовать функцию row_number windows для нумерации строк для идентификатора учетной записи и взять последнюю для каждой учетной записи:

SELECT account_id, [date], balance
FROM   (SELECT account_id, [date], balance,
               ROW_NUMBER() OVER (PARTITION BY account_id
                                  ORDER BY [date] DESC, id DESC) AS rn
        FROM   [transaction]) t
WHERE  rn = 1
...