如何在 Flask SQLAlchemy 中连接两个行数不同的表?
How can I join two tables with different number of rows in Flask SQLAlchemy?
我有两个 table 想加入。他们拥有一对多的关系。一个叫做 FundingSource,另一个叫做 AllocationSummary。它们有不同的列数和不同的行数(FundingSource 两者都有更多)。
我需要查询 FundingSource table (Table 1) 以从数据库中获取所有行,然后将 AllocationSummary (Table 2) 中的行添加到其中, 将每个相应的行连接在一起并保留剩余的 AllocationSummary (Table 2) 列值 null 因为行数较少。
结果 table 需要有来自我的 FundingSource table 的 5 列(包括 id),来自我的 AllocationSummary table 的 4 列,以及我的行数FundingSource table 有。
例如,这是我的 FundingSource table 有 5 行:
+-----------+-----------+-----------+------------+-----------+-----------+
| id | complete | department| agency | bill | cfda_no |
+-----------+-----------+-----------+------------+-----------+-----------+
| 1 | Y | Dep A | NIC | HR 3684 | 32.224 |
| 2 | Y | Dep B | AOA | HR 266m | 84.225 |
| 4 | Y | Dep C | NSK | HR 3892 | 71.20 |
| 5 | N | Dep D | NIH | HR 748 | 22.865 |
| 6 | N | Dep E | DNS | HR 1319 | 93.224 |
这是我的 AllocationSummary table,有 3 行:
+-----------+-----------+-----------+------------+-----------+-----------+
| id | state | eligible_applicant | recipient | amount |
+-----------+-----------+-----------+------------+-----------+-----------+
| 1 | NY | State | NIC | 3065.0 |
| 2 | CA | Locality | AOA | 1000.0 |
| 3 | VA | Institution | NSK | 2400.0 |
这是 RESULT table 我想要加入后:(格式被破坏所以我附上了一张照片)
Resulting Table
另请注意,我希望 id 列来自 FundingSource table,因此连接两个 table 不应创建新的 table。它应该从 FundingSource table 查询,并从 AllocationSummary table.
添加状态、eligible_applicant、收件人和金额列。
这是我的两个 table:
class FundingSource(db.Model):
id = db.Column(db.Integer, primary_key=True)
complete = db.Column(db.String(10), default=False, nullable=False)
department = db.Column(db.String(100), nullable=False)
agency = db.Column(db.String(150), nullable=False)
funding_source = db.Column(db.String(200), nullable=False)
bill = db.Column(db.String(10), nullable=False)
cfda_no = db.Column(db.Float(), nullable=True)
allocations = db.relationship('AllocationSummary', backref='allocation', lazy=True)
class AllocationSummary(db.Model):
id = db.Column(db.Integer, primary_key=True)
state = db.Column(db.String(100), nullable=False)
eligible_applicant = db.Column(db.String(100), nullable=False)
recipient = db.Column(db.String(200), nullable=False)
amount = db.Column(db.Float(), nullable=False)
funding_source_id = db.Column(db.Integer, db.ForeignKey('funding_source.id'), nullable=False)
这是我的 .py 文件:
@main.route("/")
@main.route("/guidance_master")
def g_master():
f_sources = FundingSource.query.all()
return render_template('guidance_master.html', title='Guidance Master', fsources=f_sources)
@main.route("/allocationSummary")
def alloc_summ():
all_data2 = AllocationSummary.query.join(FundingSource).filter(AllocationSummary.funding_source_id == FundingSource.id).all()
return render_template('allocationSummary.html', title='Allocation Summary', allocs=all_data2)
这是我的 HTML 文件:
....
<tbody>
{% for row in allocs%}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.complete }}</td>
<td>{{ row.agency }}</td>
<td>{{ row.funding_source }}</td>
<td>{{ row.bill }}</td>
<td>{{ row.state }}</td>
<td>{{ row.eligible_applicant }}</td>
<td>{{ row.recipient }}</td>
<td>{{ row.amount }}</td>
</tr>
{% endfor %}
</tbody>
....
我似乎无法找到一种方法来同时使用来自 2 个不同 table 的属性进行查询以显示在我的 table 中。这些是我尝试过的一些查询:
all_data2 = AllocationSummary.query.join(FundingSource).filter(AllocationSummary.funding_source_id == FundingSource.id).all()
all_data2 = db.session.query(FundingSource).outerjoin(AllocationSummary).all()
如有任何帮助,我们将不胜感激!
您可以通过以下几种方式做到这一点
1. Pandas合并
FundingSource_AllocationSummary = FundingSource.merge(AllocationSummary, how='left', on='id')
2。 SQL炼金术
import sqlalchemy
from pandasql import sqldf
FundingSource_AllocationSummary = sqldf('SELECT f.*, a.state, a.eligible_applicant, a.recipient, a.amount
FROM FundingSource as f
LEFT JOIN AllocationSummary as a
ON f.id = a.id')
您想要 FundingSource
和 AllocationSummary
之间的左外连接,您可以这样做:
rows = (
db.session.query(
FundingSource.id,
FundingSource.complete,
FundingSource.department,
FundingSource.agency,
FundingSource.bill,
FundingSource.cfda_no,
AllocationSummary.state,
AllocationSummary.eligible_applicant,
AllocationSummary.recipient,
AllocationSummary.amount,
)
.join(
AllocationSummary,
FundingSource.id == AllocationSummary.funding_source_id,
isouter=True,
)
.all()
)
上面有点繁琐,但允许HTML模板是一个简单的循环。相反 - 简单 Python 但复杂的模板 - 可以通过将 FundingSource.query.all()
传递给模板并在那里处理多个或丢失的分配来实现。
我有两个 table 想加入。他们拥有一对多的关系。一个叫做 FundingSource,另一个叫做 AllocationSummary。它们有不同的列数和不同的行数(FundingSource 两者都有更多)。
我需要查询 FundingSource table (Table 1) 以从数据库中获取所有行,然后将 AllocationSummary (Table 2) 中的行添加到其中, 将每个相应的行连接在一起并保留剩余的 AllocationSummary (Table 2) 列值 null 因为行数较少。
结果 table 需要有来自我的 FundingSource table 的 5 列(包括 id),来自我的 AllocationSummary table 的 4 列,以及我的行数FundingSource table 有。
例如,这是我的 FundingSource table 有 5 行:
+-----------+-----------+-----------+------------+-----------+-----------+
| id | complete | department| agency | bill | cfda_no |
+-----------+-----------+-----------+------------+-----------+-----------+
| 1 | Y | Dep A | NIC | HR 3684 | 32.224 |
| 2 | Y | Dep B | AOA | HR 266m | 84.225 |
| 4 | Y | Dep C | NSK | HR 3892 | 71.20 |
| 5 | N | Dep D | NIH | HR 748 | 22.865 |
| 6 | N | Dep E | DNS | HR 1319 | 93.224 |
这是我的 AllocationSummary table,有 3 行:
+-----------+-----------+-----------+------------+-----------+-----------+
| id | state | eligible_applicant | recipient | amount |
+-----------+-----------+-----------+------------+-----------+-----------+
| 1 | NY | State | NIC | 3065.0 |
| 2 | CA | Locality | AOA | 1000.0 |
| 3 | VA | Institution | NSK | 2400.0 |
这是 RESULT table 我想要加入后:(格式被破坏所以我附上了一张照片) Resulting Table
另请注意,我希望 id 列来自 FundingSource table,因此连接两个 table 不应创建新的 table。它应该从 FundingSource table 查询,并从 AllocationSummary table.
添加状态、eligible_applicant、收件人和金额列。这是我的两个 table:
class FundingSource(db.Model):
id = db.Column(db.Integer, primary_key=True)
complete = db.Column(db.String(10), default=False, nullable=False)
department = db.Column(db.String(100), nullable=False)
agency = db.Column(db.String(150), nullable=False)
funding_source = db.Column(db.String(200), nullable=False)
bill = db.Column(db.String(10), nullable=False)
cfda_no = db.Column(db.Float(), nullable=True)
allocations = db.relationship('AllocationSummary', backref='allocation', lazy=True)
class AllocationSummary(db.Model):
id = db.Column(db.Integer, primary_key=True)
state = db.Column(db.String(100), nullable=False)
eligible_applicant = db.Column(db.String(100), nullable=False)
recipient = db.Column(db.String(200), nullable=False)
amount = db.Column(db.Float(), nullable=False)
funding_source_id = db.Column(db.Integer, db.ForeignKey('funding_source.id'), nullable=False)
这是我的 .py 文件:
@main.route("/")
@main.route("/guidance_master")
def g_master():
f_sources = FundingSource.query.all()
return render_template('guidance_master.html', title='Guidance Master', fsources=f_sources)
@main.route("/allocationSummary")
def alloc_summ():
all_data2 = AllocationSummary.query.join(FundingSource).filter(AllocationSummary.funding_source_id == FundingSource.id).all()
return render_template('allocationSummary.html', title='Allocation Summary', allocs=all_data2)
这是我的 HTML 文件:
....
<tbody>
{% for row in allocs%}
<tr>
<td>{{ row.id }}</td>
<td>{{ row.complete }}</td>
<td>{{ row.agency }}</td>
<td>{{ row.funding_source }}</td>
<td>{{ row.bill }}</td>
<td>{{ row.state }}</td>
<td>{{ row.eligible_applicant }}</td>
<td>{{ row.recipient }}</td>
<td>{{ row.amount }}</td>
</tr>
{% endfor %}
</tbody>
....
我似乎无法找到一种方法来同时使用来自 2 个不同 table 的属性进行查询以显示在我的 table 中。这些是我尝试过的一些查询:
all_data2 = AllocationSummary.query.join(FundingSource).filter(AllocationSummary.funding_source_id == FundingSource.id).all()
all_data2 = db.session.query(FundingSource).outerjoin(AllocationSummary).all()
如有任何帮助,我们将不胜感激!
您可以通过以下几种方式做到这一点
1. Pandas合并
FundingSource_AllocationSummary = FundingSource.merge(AllocationSummary, how='left', on='id')
2。 SQL炼金术
import sqlalchemy
from pandasql import sqldf
FundingSource_AllocationSummary = sqldf('SELECT f.*, a.state, a.eligible_applicant, a.recipient, a.amount
FROM FundingSource as f
LEFT JOIN AllocationSummary as a
ON f.id = a.id')
您想要 FundingSource
和 AllocationSummary
之间的左外连接,您可以这样做:
rows = (
db.session.query(
FundingSource.id,
FundingSource.complete,
FundingSource.department,
FundingSource.agency,
FundingSource.bill,
FundingSource.cfda_no,
AllocationSummary.state,
AllocationSummary.eligible_applicant,
AllocationSummary.recipient,
AllocationSummary.amount,
)
.join(
AllocationSummary,
FundingSource.id == AllocationSummary.funding_source_id,
isouter=True,
)
.all()
)
上面有点繁琐,但允许HTML模板是一个简单的循环。相反 - 简单 Python 但复杂的模板 - 可以通过将 FundingSource.query.all()
传递给模板并在那里处理多个或丢失的分配来实现。