- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用 Django 从 ORM 生成的 SQL 时遇到问题。
Cartons
通过 cartons_shipments
与 Shipments
具有多对多关系。
我希望排除至少有一个 INBOUND
纸箱状态为 ['TRANSIT', 'DELIVERED', 'FAILURE']
的货件.
但是我没有得到预期的结果,所以我打开了 SQL 日志记录。
return Shipment.objects.filter(
... # other filtering
# does not have any inbound cartons in_transit/delivered/failed
~Q(
Q(cartons__type='INBOUND') &
Q(cartons__status__in=['TRANSIT', 'DELIVERED', 'FAILURE'])
) &
).distinct()
我也尝试过将此作为我的过滤器,但得到了相同的 SQL 输出。
~Q(
cartons__type='INBOUND',
cartons__status__in=['TRANSIT', 'DELIVERED', 'FAILURE']
)
这会生成以下 SQL:
AND NOT (
"shipments"."id" IN (
SELECT U1."shipment_id"
FROM "cartons_shipments" U1
INNER JOIN "cartons" U2 ON (U1."carton_id" = U2."id")
WHERE U2."type" = 'INBOUND'
)
AND "shipments"."id" IN (
SELECT U1."shipment_id" FROM "cartons_shipments" U1
INNER JOIN "cartons" U2 ON (U1."carton_id" = U2."id")
WHERE U2."status" IN ('TRANSIT', 'DELIVERED', 'FAILURE')
)
)
但这并不正确,因为它会排除具有任何 INBOUND
纸箱的货件以及任何 纸箱(不一定INBOUND
纸箱)的状态为 ['TRANSIT', 'DELIVERED', 'FAILURE']
。我需要结合这个逻辑。
此外,现在我正在运行 2 个子选择,并且性能受到显着影响,因为我们有大量处于这些状态的纸箱。
正确的 SQL 应该是这样的:
AND NOT ("shipments"."id" IN (
SELECT U1."shipment_id"
FROM "cartons_shipments" U1
INNER JOIN "cartons" U2 ON (U1."carton_id" = U2."id")
WHERE U2."type" = 'INBOUND'
and U2."status" IN ('TRANSIT', 'DELIVERED', 'FAILURE')
))
这样我就可以只排除处于这些状态的 INBOUND
纸箱的货件。
这两者之间的查询时间很长,当然我能够通过第二个 SQL 示例获得正确的结果。我认为我可以通过组合 Q()
对象来组合该逻辑。但想不通。
我还认为也许我可以纠正第二个示例中的原始 SQL。但我很难弄清楚如何将原始 sql 与其他 ORM 过滤器结合起来。
任何帮助将不胜感激。
<小时/>编辑:
我可以通过在代码中进行过滤并从查询中删除过滤器来获得正确的结果:
returned_cartons = Carton.objects.prefetch_related('shipments').filter(
type='INBOUND',
status__in=['TRANSIT', 'DELIVERED', 'FAILURE']
)
returned_shipment_ids = list(map(
lambda carton: carton.shipments.first().id,
returned_cartons
))
return list(filter(
lambda shipment: shipment.id not in returned_shipment_ids,
shipments
))
不幸的是,这太慢了,没有什么用处。
<小时/>基于 Endre Both 想法的最终解决方案 🙌
return Shipment.objects.filter(
..., # other filtering
# has at least 1 inbound carton
Q(cartons__type='INBOUND')
).exclude(
# we want to exclude shipments that have at least 1 inbound cartons
# with a status in transit/delivered/failure
id__in=Shipment.objects.filter(
..., # filters to limit the number of records returned
cartons__type='INBOUND',
cartons__status__in=['TRANSIT', 'DELIVERED', 'FAILURE'],
).distinct()
).distinct()
此行 Q(cartons__type='INBOUND')
是必需的,因为我们排除 ['TRANSIT', 'DELIVERED' 中具有
状态。但我们也会保留没有纸箱的 cargo 。INBOUND
纸箱的货件', 'FAILURE']
希望这可以帮助更多的人。
最佳答案
对于我们这些凡人来说,ORM 中的“M”有时可能有点难以理解。但你可以尝试一种不同的、更简单的方法。它仍然使用子查询而不是联接,但这不一定会拖累性能。
Shipment.objects.exclude(
id__in=Cartons.objects
.filter(type='INBOUND',
status__in=['TRANSIT', 'DELIVERED', 'FAILURE'])
.values('shipments__id')
.distinct()
)
从 Carton
模型返回到 Shipment
主键的引用的确切名称取决于模型的确切定义。我使用了 shipments__id
,但也可能是 shipment_set__id
或其他内容。
新想法:您需要将子选择基于中间模型而不是Cartons
。如果你有一个明确的中间模型,这很容易,如果没有,你首先需要一个 Shipment
或 Cartons
对象,因为据我所知你无法获得仅从实例从类本身引用中间模型。
IModel = Shipment.objects.first().cartons.through
Shipment.objects.exclude(
id__in=IModel.objects
.filter(cartons__type='INBOUND',
cartons__status__in=['TRANSIT', 'DELIVERED', 'FAILURE'])
.values('shipment__id')
.distinct()
)
关于python - Django ORM 无法为不在其中的多对多生成正确的 SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55540927/
SQL、PL-SQL 和 T-SQL 之间有什么区别? 谁能解释一下这三者之间的区别,并提供每一个的相关使用场景? 最佳答案 SQL 是一种对集合进行操作的查询语言。 它或多或少是标准化的,几乎所有关
这个问题已经有答案了: What is the difference between SQL, PL-SQL and T-SQL? (6 个回答) 已关闭 9 年前。 我对 SQL 的了解足以完成我的
我在数据库中有一个 USER 表。该表有一个 RegistrationDate 列,该列有一个默认约束为 GETDATE()。 使用 LINQ 时,我没有为 RegistrationDate 列提供任
我有一个可能属于以下类型的字符串 string expected result 15-th-rp 15 15/12-rp 12 15-12-th
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 9年前关闭
我有一个存储过程(称为 sprocGetArticles),它从文章表中返回文章列表。这个存储过程没有任何参数。 用户可以对每篇文章发表评论,我将这些评论存储在由文章 ID 链接的评论表中。 有什么方
我目前正在做一个 *cough*Oracle*cough* 数据库主题。讲师介绍embedded SQL作为让其他语言(例如 C、C++)与(Oracle)数据库交互的方式。 我自己做了一些数据库工作
SQL Server 中 SQL 语句的最大长度是多少?这个长度是否取决于 SQL Server 的版本? 例如,在 DECLARE @SQLStatement NVARCHAR(MAX) = N'S
这个问题已经有答案了: Simple way to transpose columns and rows in SQL? (9 个回答) 已关闭 8 年前。 CallType
预先感谢您对此提供的任何帮助。 假设我有一个查询,可以比较跨年的数据,从某个任意年份开始,永无止境(进入 future ),每年同一时期直到最后一个完整的月份(其特点是一月数据永远不会显示至 2 月
我在数据库中有一个 USER 表。该表有一个 RegistrationDate 列,该列的默认约束为 GETDATE()。 使用 LINQ 时,我没有为 RegistrationDate 列提供任何数
下面是我试图用来检查存储过程是否不存在然后创建过程的 sql。它会抛出一个错误:Incorrect syntax near the keyword 'PROCEDURE' IF NOT EXISTS
我有一个同事声称动态 SQL 在许多情况下比静态 SQL 执行得更快,所以我经常看到 DSQL 到处都是。除了明显的缺点,比如在运行之前无法检测到错误并且更难阅读,这是否准确?当我问他为什么一直使用
来自 lobodava 的动态 SQL 查询是: declare @sql nvarchar(4000) = N';with cteColumnts (ORDINAL_POSITION, CO
使用 SQL Server 中的存储过程执行动态 SQL 命令的现实优点和缺点是什么 EXEC (@SQL) 对比 EXEC SP_EXECUTESQL @SQL ? 最佳答案 sp_executes
我有这个有效的 SQL 查询: select sum(dbos.Points) as Points, dboseasons.Year from dbo.StatLines dbos i
我正在调试一些构建成功运行的 SQL 命令的代码。 然而,在查询结束时,查询结果似乎被写入了一个文本文件。 完整的查询如下 echo SELECT DATE,DATETABLE,DATE,APPDAT
我有一些创建表的 .sql 文件(MS SQL 数据库): 表_1.sql: IF OBJECT_ID (N'my_schema.table1', N'U') IS NOT NULL DROP TAB
我写了下面的 SQL 存储过程,它一直给我错误@pid = SELECT MAX(... 整个过程是: Alter PROCEDURE insert_partyco @pname varchar(20
我在 SQL Server 2005 中有包含两列 Fruit 和 Color 的表,如下所示 Fruit Colour Apple Red Orange
我是一名优秀的程序员,十分优秀!