Django ORM:具有后续过滤功能的窗口函数

时间:2018-07-25 11:05:14

标签: python django django-orm

回答this question,我found out不允许将窗口函数与filter结合使用(从技术上讲,它们是允许的,但是filter子句会影响窗口)。有一个提示可以将窗口函数包装在内部查询中,以便最终的SQL看起来像这样(据我了解):

SELECT * FROM (
    SELECT *, *window_function* FROM TABLE)
WHERE *filtering_conditions*

问题是:如何使用Django ORM编写此查询?

3 个答案:

答案 0 :(得分:4)

另一种解决方案是通用表表达式(CTE),借助django-cte,您可以实现所需的目标:

cte = With(
    YouModel.objects.annotate(
        your_window_function=Window(...),
    )
)

qs = cte.queryset().with_cte(cte).filter(your_window_function='something')

大致翻译为:

WITH cte as (
    SELECT *, WINDOW(...) as your_window_function
    FROM yourmodel
) 
SELECT * 
FROM cte
WHERE cte.your_window_function = 'something'

答案 1 :(得分:2)

There are developers interested in solving it,但现在ORM无法实现。

一种建议的解决方案是添加一个QuerySet.subquery().wrap()方法,以便在子查询中查询集,然后对其进行过滤。

答案 2 :(得分:-1)

您需要使用原始查询。为了一次执行多个查询。了解更多信息,django documentation

from time import sleep, strftime
from bcc import BPF
from bcc.utils import printb
from bcc.syscall import syscall_name, syscalls
from ctypes import *


    b = BPF(text = """

    BPF_HASH(start, u32, u64);


    TRACEPOINT_PROBE(raw_syscalls, sys_exit)
    {
        u32 syscall_id = args->id;
        u32 key = 1;
        u64 *val;
        u32 uid = bpf_get_current_uid_gid();

        if (uid == 0)
        {
            val = start.lookup(&key); //find value associated with key 1
            if (val)
                bpf_trace_printk("Hello world, I have value %d!\\n", *val);

        }
        return 0;
    }
    """)

    thisStart = b["start"]
    thisStart[c_int(1)] = c_int(9) #insert key-value part 1->9


    while 1:
        try:
            (task, pid, cpu, flags, ts, msg) = b.trace_fields()
        except KeyboardInterrupt:
            print("Detaching")
            exit()
        print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))

您可以做的其他事情如下。

model.py

clear
#!/bin/bash
echo This is the current year.
Year="date '+%Y'"
$Year
echo This is the time:
date "+%r"
Date='cal 2000'
echo  This is the calendar list for the year 2000
$Date

querySet.py

for p in Person.objects.raw('''
    SELECT * FROM (SELECT *, *window_function* FROM TABLE)
    WHERE *filtering_conditions*'''):
    print(p)
# John Smith
# Jane Jones

生成的SQL看起来像这样。

class Category(models.Model):
    name = models.CharField(max_length=100)


class Hero(models.Model):
    # ...
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

    benevolence_factor = models.PositiveSmallIntegerField(
        help_text="How benevolent this hero is?",
        default=50
    )