SQLAlchemy 仅从连接表中选择列

Posted

技术标签:

【中文标题】SQLAlchemy 仅从连接表中选择列【英文标题】:SQL Alchemy select columns from joined tables only 【发布时间】:2022-01-03 17:29:17 【问题描述】:

我想以 orm 方式运行一个有效的 sql 原始查询。我需要从加入的表中选择列和列数的地方,而不是来自主的任何列。如何以 ORM 方式实现。

我的原始查询(我通常在 sql server 中使用):

原始 SQL:

 SELECT [barcode].[dbo].[Tbl_ProductionMaster].[ProductionName]
       ,[barcode].[dbo].[Tbl_barcode].[Size]
       ,COUNT([barcode].[dbo].[Tbl_barcode].[Size])
   FROM [barcode].[dbo].[tbl_ProductionScan]
   INNER JOIN [barcode].[dbo].[Tbl_barcode] ON [barcode].[dbo].[Tbl_barcode].[Serial_no] = [barcode].[dbo].[tbl_ProductionScan].[serial_no]
   INNER JOIN [barcode].[dbo].[Tbl_ProductionMaster] ON [barcode].[dbo].[Tbl_ProductionMaster].[ProductionCode] = [barcode].[dbo].[Tbl_barcode].[Product_code]
   WHERE [barcode].[dbo].[tbl_ProductionScan].[prod_date] BETWEEN '2021-08-01 08:00:00' AND '2021-08-25 08:00:00' AND [barcode].[dbo].[Tbl_ProductionMaster].[ProductionName] Like '%3780%black%'
   GROUP BY [barcode].[dbo].[Tbl_ProductionMaster].[ProductionName], [barcode].[dbo].[Tbl_barcode].[Size]

我在 SQL Alchemy 中所做的事情:

 result = (
 session.query(ProductionMaster.article, Barcode.size, sa.func.count(Barcode.size))
 .join(Barcode, Barcode.serial_no == ProductionScan.serial_no)
 .join(ProductionMaster, ProductionMaster.prod_code == Barcode.prod_code)
 .filter(
     sa.and_(
         ProductionScan.date >= "2021-08-01 08:00:00",
         ProductionScan.date <= "2021-08-25 08:00:00",
         ProductionMaster.article.like("%3780%black%"),
     )
 )
 .group_by(ProductionMaster.article, Barcode.size)
 .all()

由于返回的原始查询不正确,因此运行出错。

错误:

 The multi-part identifier "tbl_ProductionScan.serial_no" could not be bound. (4104) (SQLExecDirectW)')

从 sqlalchemy 错误返回的原始 sql:

 [SQL: SELECT [Tbl_ProductionMaster].[ProductionName] AS [Tbl_ProductionMaster_ProductionName], [Tbl_barcode].[Size] AS [Tbl_barcode_Size], count([Tbl_barcode].[Size]) AS count_1
 FROM [tbl_ProductionScan], [Tbl_ProductionMaster] JOIN [Tbl_barcode] ON [Tbl_barcode].serial_no = [tbl_ProductionScan].serial_no JOIN [Tbl_ProductionMaster] ON [Tbl_ProductionMaster].[ProductionCode] = [Tbl_barcode].[Product_Code]
 WHERE [tbl_ProductionScan].prod_date >= ? AND [tbl_ProductionScan].prod_date <= ? AND [Tbl_ProductionMaster].[ProductionName] LIKE ? GROUP BY [Tbl_ProductionMaster].[ProductionName], [Tbl_barcode].[Size]]

在这个 sqlalchemy 查询中,我如何在 FROM 关键字中获得 Tbl_ProductionScan 的乘车体验。我只需要Tbl_ProductionScan,所有其余的表Tbl_ProductionMasterTbl_Barcode 仅在JOIN 关键字中。这样 sqlalchemy orm 匹配我在顶部给出的实际原始查询。

【问题讨论】:

这也可以通过添加 select_from optionresult = ( session.query(ProductionMaster.article, Barcode.size, sa.func.count(Barcode.size)).select_from(ProductionScan) .join(Barcode, Barcode.serial_no == ProductionScan.serial_no) .join(ProductionMaster, ProductionMaster.prod_code == Barcode.prod_code) .filter( sa.and_( ProductionScan.date &gt;= "2021-08-01 08:00:00", ProductionScan.date &lt;= "2021-08-25 08:00:00", ProductionMaster.article.like("%3780%black%"), ) ) .group_by(ProductionMaster.article, Barcode.size) .all() 【参考方案1】:

我知道过滤,请确保您将字符串转换为日期,并且您是否尝试过滤两个字符串值(使用或)或一个

start_date = datetime.strptime("2021-08-01 08:00:00", "%Y-%m-%d %H:%M:%S")
end_date = datetime.strptime("2021-08-25 08:00:00", "%Y-%m-%d %H:%M:%S")
search = "%%%".format("3780", "black")

然后尝试运行它

result = session.query(ProductionScan, ProductionMaster, Barcode, )
    .join(Barcode, Barcode.serial_no == ProductionScan.serial_no)
    .join(ProductionMaster, ProductionMaster.prod_code == Barcode.prod_code)
    .filter(
        sa.and_(
            ProductionScan.date >= start_date,
            ProductionScan.date <= end_date,
            ProductionMaster.article.like(search),
            # sa.or_(ProductionMaster.article.like(search1), ProductionMaster.article.like(search2))
        )
    )
    .filter(Barcode.serial_no.isnot(None))
    .with_entities(ProductionMaster.article.label('article'), Barcode.size.label('size'), sa.func.count(Barcode.size).label('count'))
    .group_by(ProductionMaster.article, Barcode.size)
    .all()

with_entities

返回一个新的查询,用给定的实体替换 SELECT 列表。

【讨论】:

您的解决方案运行良好,但我只需在查询语句之后和在我的代码中加入表之前添加 .select_from(ProductionScan) 即可获得结果。 那么这两个在查询中的效果是一样的?

以上是关于SQLAlchemy 仅从连接表中选择列的主要内容,如果未能解决你的问题,请参考以下文章

仅从表中选择一些列

休眠:仅从一个表中选择所有而不是 3 个连接表

如何在sqlalchemy中选择多列连接的特定列?

SqlAlchemy ORM - 在查询时限制列(选择) - column_property

仅从连接表中获取指定的列

SQLAlchemy 单个查询从两个表中返回列