【问题标题】:Filter SQL elements with adjacent ID过滤 ID 相邻的 SQL 元素
【发布时间】:2019-02-26 19:33:32
【问题描述】:

我真的不知道如何在标题中正确陈述这个问题。

假设我有一张表Word,如下所示:

| id  | text   |
| --- | ---    |
|  0  | Hello  |
|  1  | Adam   |
|  2  | Hello  |
|  3  | Max    |
|  4  | foo    |
|  5  | bar    |

是否可以根据text查询这张表,并接收到主键(id)正好为1的对象?

如果我这样做了

Word.objects.filter(text='Hello')

我得到一个包含行的QuerySet

| id  | text   |
| --- | ---    |
|  0  | Hello  |
|  2  | Hello  |

但我想要行

| id  | text   |
| --- | ---    |
|  1  | Adam   |
|  3  | Max    |

我想我能做到

word_ids = Word.objects.filter(text='Hello').values_list('id', flat=True)
word_ids = [w_id + 1 for w_id in word_ids]  # or use a numpy array for this
Word.objects.filter(id__in=word_ids)

但这似乎并不太有效。是否有一种直接的 SQL 方法可以在一次调用中执行此操作?最好直接使用Django的QuerySets?

编辑: 这个想法实际上是我想过滤第二个查询集中的那些词。比如:

Word.objects.filter(text__of__previous__word='Hello', text='Max')

【问题讨论】:

    标签: python sql django postgresql django-models


    【解决方案1】:

    在普通 Postgres 中,您可以使用 lag 窗口函数 (https://www.postgresql.org/docs/current/static/functions-window.html)

    SELECT 
        id, 
        name 
    FROM (
        SELECT 
            *, 
            lag(name) OVER (ORDER BY id) as prev_name
        FROM test
    ) s
    WHERE prev_name = 'Hello'
    

    lag 函数添加一个包含前一行文本的列。因此,您可以在子查询中按此文本进行过滤。

    demo:db<>fiddle


    我不是很喜欢 Django,但documentation 的意思是,在 2.0 版中添加了窗口函数的功能。

    【讨论】:

    • 这太好了,谢谢!特别是演示小提琴。由于我目前使用的是 django 1.11,因此我将使用原始 sql 语句。你能向我解释一下s 是什么意思吗?为什么会在那里?
    • 在 Postgres 中,每个子查询都需要一个别名。所以我简单地将子查询命名为“s”。它仅用于语法目的,但不包含任何魔法:)
    【解决方案2】:

    如果“1 off”的意思是差值正好是 1,那么你可以这样做:

    select w.*
    from w
    where w.id in (select w2.id + 1 from words w2 where w2.text = 'Hello');
    

    lag()也是一个非常合理的解决方案。这似乎是对您问题的直接解释。如果你有差距(并且意图是+ 1),那么lag() 有点棘手。

    【讨论】:

    • 更棘手的意思是lag 仍然会返回“下一个”pk,即使它不是+1
    • @MoRe 。 . .是的。所以这取决于“1 off”的字面意思是否意味着ids 之间的差异为1。或者“1 off”是否更具比喻性,只是表示之前的id
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-20
    • 2023-03-17
    • 2023-03-26
    • 1970-01-01
    相关资源
    最近更新 更多