0

原始查询本身是正确的,我能够从数据库中检索原始查询集。我需要将其转换为查询集以进行进一步处理,并且我面临以下错误。

创建相应的 django 查询对我来说很难,这就是我创建 SQL 查询、获取原始查询集并现在尝试将其转换为查询集以进行进一步处理的原因。

为了匿名,我更改了 django 模型名称和表名称。

这是我在 django shell 中尝试的输出。我能够执行以下查询,但是当我尝试访问下面的“queryset”时收到错误“django.db.utils.ProgrammingError: subquery has too many columns”。

from django.db.models.expressions import RawSQL
from xyz.models import *
value = '1.2.3.4'
queryset = Test1.objects.filter(id__in=RawSQL("SELECT DISTINCT ON (test1.start_time, test1.id) test1.id, test1.name, test1.start_time FROM test1 WHERE EXISTS (SELECT * FROM test2 JOIN test3 ON test2.test3_id = test3.id AND test3.value = %s JOIN test4 ON test2.test4_id = test4.id AND test4.test1_id = test1.id) ORDER BY test1.start_time DESC", params=[value]))

为了便于阅读,我已经格式化了下面使用的查询。

SELECT
  DISTINCT ON (test1.start_time, test1.id)
  test1.id,
  test1.name,
  test1.start_time
FROM
  test1
WHERE
  EXISTS (
    SELECT
      *
    FROM
      test2
      JOIN test3 ON test2.test3_id = test3.id
      AND test3.value = 'value'
      JOIN test4 ON test2.test4_id = test4.id
      AND test4.test1_id = test1.id
  )
ORDER BY
  test1.start_time DESC
4

2 回答 2

2

如错误所示,您选择的列太多,您的过滤条件不需要。当您过滤字段时,子查询必须仅选择Test1表字段。所以基本上你的子查询应该只像这样投影字段:ididid

SELECT
  test1.id
FROM
  test1
WHERE
  EXISTS (
    SELECT
      *
    FROM
      test2
      JOIN test3 ON test2.test3_id = test3.id
      AND test3.value = 'value'
      JOIN test4 ON test2.test4_id = test4.id
      AND test4.test1_id = test1.id
  )
ORDER BY
  test1.start_time DESC

所以你的最终查询集应该是这样的:

queryset = Test1.objects.filter(id__in=RawSQL("SELECT test1.id FROM test1 WHERE EXISTS (SELECT * FROM test2 JOIN test3 ON test2.test3_id = test3.id AND test3.value = %s JOIN test4 ON test2.test4_id = test4.id AND test4.test1_id = test1.id) ORDER BY test1.start_time DESC", params=[value]))
于 2021-04-08T03:38:32.160 回答
1

你根本不需要 RawSQL

from django.db.models import Exists, OuterRef

queryset = Test1.objects.filter(
    Exists(Test2.objects.filter(
        test3__value=value,
        test4__test1_id=OuterRef('id')
    )
)

我不确定您的 django 型号名称,所以test3, test4, 并且test1在您的示例中可能会有所不同。

于 2021-04-15T05:58:30.140 回答