我想在特定日期之前找到每个帐户的最后一笔交易
I want to find the last transaction for each account prior to a certain date
我有一个 table 定义(在 Azure SQL 服务器上)如下:
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)
)
我想查找每个帐户在特定日期之前的最后余额。我需要 returned 的列是:account_id、日期、余额。
我试过:
select account_id, max(date) as date
from dbo.[transaction]
group by account_id
这有效,但它不会 return 余额。
其次,我的交易首先按日期排序,然后按 ID 排序。所以如果最大日期发生多笔交易,它应该选择具有最高id的交易上的余额。
我的应用程序是用 flask-sqlalchemy 编写的,所以 sqlalchemy 的答案会很好,但我也很高兴 SQL 中的答案。
您可以使用 row_number
windows 函数为每个帐户 ID 的行编号,并为每个帐户取最后一行:
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
解决方案:包括您的日期检查
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
提供的两个答案同样出色。
我已经将其转换为 python sqlalchemy 答案以供参考:
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 排序。
我有一个 table 定义(在 Azure SQL 服务器上)如下:
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)
)
我想查找每个帐户在特定日期之前的最后余额。我需要 returned 的列是:account_id、日期、余额。
我试过:
select account_id, max(date) as date
from dbo.[transaction]
group by account_id
这有效,但它不会 return 余额。
其次,我的交易首先按日期排序,然后按 ID 排序。所以如果最大日期发生多笔交易,它应该选择具有最高id的交易上的余额。
我的应用程序是用 flask-sqlalchemy 编写的,所以 sqlalchemy 的答案会很好,但我也很高兴 SQL 中的答案。
您可以使用 row_number
windows 函数为每个帐户 ID 的行编号,并为每个帐户取最后一行:
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
解决方案:包括您的日期检查
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
提供的两个答案同样出色。
我已经将其转换为 python sqlalchemy 答案以供参考:
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 排序。