合并两个查询集或重新排序一个QS,这样每n个元素将从第二个开始

2024-06-01 12:11:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我不确定是否可以只使用DjangoORM或纯SQL来完成。我有一个Fruit模型,我想呈现一个水果列表,这样每个并且只有第n个水果是type="apple"。你知道吗

因此,对于4来说:

  • 除了苹果还有别的水果吗
  • 除了苹果还有别的水果吗
  • 除了苹果还有别的水果吗
  • 苹果
  • 除了苹果还有别的水果吗
  • 除了苹果还有别的水果吗 ... 你知道吗

我正在寻找一种比拥有一大堆水果更有效的方法,最好是一个QuerySet,但不确定这是否可行。你知道吗

fruits_except_apples = Fruit.objects.exclude(type='apple')
apples = Fruit.objects.filter(type='apple')

我甚至可以创建两个QuerySets,然后以某种方式合并它们或者只是重新排序一个QuerySet。你知道吗


Tags: 方法模型苹果apple列表sqlobjectstype
1条回答
网友
1楼 · 发布于 2024-06-01 12:11:07

我不知道这是否有帮助,但这个查询命令的水果在你的方式。但我相信这可以在循环(SQL函数或python)中以更有效的方式完成。你知道吗

demo:db<>fiddle

SELECT 
    name, type
FROM (
    SELECT 
        name, type, 
        row_number + (row_number - 1) / 3 as row_number
    FROM (
        SELECT 
           *,
           row_number() OVER ()
        FROM fruits
        WHERE type != 'apple'
    )s

    UNION

    SELECT
        *,
        4 * row_number() OVER ()
    FROM fruits
    WHERE type = 'apple'
) s
ORDER BY row_number

逐步解释:

主要的问题是得到一个有两个不同行数的订单:一个有4步(4,8,12,…),一个有1步但没有4步(1,2,3,5,6,7,9,…),这才是真正的问题。你知道吗


我的桌子

| name |      type |
|   |     -|
|   A1 |     apple |
|   A2 |     apple |
|   A3 |     apple |
|   B1 |    banana |
|   B2 |    banana |
|   B3 |    banana |
|   B4 |    banana |
|   O1 |    orange |
|   K1 |      kiwi |
|   K2 |      kiwi |
|   K3 |      kiwi |
|   C1 | chocolate |
|   C2 | chocolate |

第一部分。获取非苹果的订单:

使用window functionrow_number。这将在数据中添加行计数列:

SELECT 
    *,
    row_number() OVER ()
FROM fruits
WHERE type != 'apple'

name  type       row_number  
        -         
B1    banana     1           
B2    banana     2           
B3    banana     3           
B4    banana     4           
O1    orange     5           
K1    kiwi       6           
K2    kiwi       7           
K3    kiwi       8           
C1    chocolate  9           
C2    chocolate  10  

现在我们必须创造差距。为此,有必要移动3的块:ids 4,5,6应该变成5,6,7;ids 7,8,9应该变成9,10,11,依此类推。你知道吗

3的块可以在下一个子选择中用row_number的整数除法实现:

SELECT 
     *, 
     row_number / 3
FROM (
    SELECT 
        *,
        row_number() OVER ()
    FROM fruits
    WHERE type != 'apple'
)s

这给了

name  type       row_number  ?column?  
        -               
B1    banana     1           0         
B2    banana     2           0         
B3    banana     3           1         
B4    banana     4           1         
O1    orange     5           1         
K1    kiwi       6           2         
K2    kiwi       7           2         
K3    kiwi       8           2         
C1    chocolate  9           3         
C2    chocolate  10          3  

我们可以看到,简单的划分仍然是移位的。所以减去1我们得到了我们期望的结果:

SELECT 
     *, 
     (row_number - 1) / 3
FROM (
    SELECT 
        *,
        row_number() OVER ()
    FROM fruits
    WHERE type != 'apple'
)s   

这给了

name  type       row_number  ?column?  
        -               
B1    banana     1           0         
B2    banana     2           0         
B3    banana     3           0         
B4    banana     4           1         
O1    orange     5           1         
K1    kiwi       6           1         
K2    kiwi       7           2         
K3    kiwi       8           2         
C1    chocolate  9           2         
C2    chocolate  10          3   

现在我们可以看到,我们可以添加两个最右边的列来实现我们的结果:

SELECT 
     *, 
     (row_number - 1) / 3 + row_number
FROM (
    SELECT 
        *,
        row_number() OVER ()
    FROM fruits
    WHERE type != 'apple'
)s  

这给了

name  type       row_number  ?column?  
        -               
B1    banana     1           1         
B2    banana     2           2         
B3    banana     3           3         
B4    banana     4           5         
O1    orange     5           6         
K1    kiwi       6           7         
K2    kiwi       7           9         
K3    kiwi       8           10        
C1    chocolate  9           11        
C2    chocolate  10          13   

为了得到appleid,我们只需再次使用row_number()函数,它用(1,2,3,…)枚举apple行。然后我们将这些ID与4相乘得到(4,8,12,…)。你知道吗

这两个部分可以通过UNION连接,然后必须按照它们生成的id排序。你知道吗

相关问题 更多 >